[C言語] 関数を指すポインタ [その2]

コールバック関数

#include<stdio.h>
#include<math.h>

double callback(double x){
    return x+1.0;
}

double g(double x, double (*f)(double)){
    return f(x);
}

int main(void) {
    
    double ans = g(5.0, callback); 
    printf("ans = %g\n", ans);

    ans = g(5.0, sqrt);
    printf("ans = %g\n", ans);

    return 0;
}

$ gcc main.c -o main -lm && ./main
ans = 6
ans = 2.23607

関数を呼び出す際に、引数はポインタで指定する

double callback(double x, double y){
    return x+y;
}

double g(double x, double (*f)(double,double)){
    return f(x, x);
}

int main(void) {
    
    double ans = g(5.0, callback); 
    printf("ans = %g\n", ans);

    ans = g(5.0, pow);
    printf("ans = %g\n", ans);

    return 0;
}

$ gcc main.c -o main -lm && ./main
ans = 10
ans = 3125
不思議な感じがしてくる

### シグナル処理関数
シグナルとは. プロセスやプロセスグループへ様々なイベントを通知するためにあるカーネルの機能 (ソフトウェア割り込み)。

#include<stdio.h>
#include<signal.h>

void printMessage(int sigNo){
    printf("割り込み発生:シグナル=%d\n", sigNo);
}

int main(void) {
    
    int x[1];
    int y;

    if(signal(SIGSEGV, printMessage) != SIG_ERR)
        fprintf(stderr, "シグナル設定成功\n");
    else
        fprintf(stderr, "シグナル設定失敗\n");
    y = x[10000];

    printf("プログラム終了: これは実行されません\n");

    return 0;
}

なんだこれは…

### プログラム終了時の実行関数登録

void pr1(void) {
    printf("pr1 called\n");
}
void pr2(void) {
    printf("pr2 called\n");
}
void pr3(void) {
    printf("pr3 called\n");
}

int main(void) {
    
    if(!atexit(pr1)) printf("pr1 OK\n"); else printf("pr1 No\n");
    if(!atexit(pr2)) printf("pr2 OK\n"); else printf("pr2 No\n");
    if(!atexit(pr3)) printf("pr3 OK\n"); else printf("pr3 No\n");

    return 0;
}

$ gcc main.c -o main -lm && ./main
pr1 OK
pr2 OK
pr3 OK
pr3 called
pr2 called
pr1 called
ん?

### バイナリサーチ

int compare(const int *n1, const int *n2){
    printf("%d %d\n", *n1, *n2);
    return *n1 - *n2;
}

int main(void) {
    
    int data[] = {-2, 0, 1, 3, 5, 6, 9, 10, 11, 12, 100,};
    int num = sizeof data / sizeof data[0];

    int target = 0;
    int *t;

    if((t = (int *)bsearch(&target, data, num, sizeof(data[0]), (int(*)(const void*, const void*))compare))!= NULL)
        printf("%dがありました。\n", *t);
    else
        printf("%dがありませんでした。\n", target);
    return 0;
}

$ gcc main.c -o main -lm && ./main
0 6
0 1
0 0
0がありました。
どういう流れかよくわからん…

### 文字列のバイナリサーチ

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int compare(const char *name1, const char **name2){
    printf("%s %s\n", name1, *name2);
    return strcmp(name1, *name2);
}

int main(void) {
    
    char *names[] = {"atexit", "atol", "bsearch", "calloc", "malloc", "qsort","rand", "system", "wcstombs"};
    int num = sizeof names / sizeof names[0];

    char *name = "atol"; //検索する文字列
    char **s; // ポインタのポインタ

    if((s = bsearch(name, names, num, sizeof names[0], (int(*)(const void*, const void*))compare))!= NULL)
        printf("%sがありました。\n", *s);
    else
        printf("%sがありませんでした。\n", name);
    return 0;
}

$ gcc main.c -o main -lm && ./main
atol malloc
atol bsearch
atol atol
atolがありました。

strcmpでcompareしているのはわかるが、なぜ連続になるのだろうか…

### クイックソート

int compare(const int *n1, const int *n2){
    return *n1 - *n2;
}

int main(void) {
    
    int data[] = {4, 2, -2, 8, -9, 6, 4, 2, 1, 0, 17, -3, 23};
    int num = sizeof data / sizeof data[0];

    int k;

    qsort(data, num, sizeof(data[0]), (int(*)(const void*, const void*)) compare);

    for(k=0; k<num; k++)
        printf("%d ", data[k]);
    printf("\n");
    return 0;
}

$ gcc main.c -o main -lm && ./main
-9 -3 -2 0 1 2 2 4 4 6 8 17 23

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int compare( const char **name1, const char **name2 ) /* 比較関数 */
{
	printf( "%s, %s\n", *name1, *name2 ); /* テスト用表示:実際には不要 */
	return strcmp( *name1, *name2 );
}

int main( void )
{
	char *names[] = { "rand", "calloc", "malloc", "wcstombs", "atol", "qsort", "atexit", "system", "bsearch", };
	int  num = sizeof names / sizeof names[0];

	int k;

	qsort( names, num, sizeof( names[0] ), (int (*)(const void *, const void * ))compare );

	for( k=0; k<num; k++ ) /* 結果の表示 */
		printf( "%s ", names[k] );
	printf( "\n" );

	return 0;
}

$ gcc main.c -o main -lm && ./main
rand, calloc
malloc, wcstombs
calloc, malloc
rand, malloc
rand, wcstombs
atol, qsort
system, bsearch
atexit, bsearch
atol, atexit
atol, bsearch
qsort, bsearch
qsort, system
calloc, atexit
calloc, atol
calloc, bsearch
calloc, qsort
malloc, qsort
rand, qsort
rand, system
wcstombs, system
atexit atol bsearch calloc malloc qsort rand system wcstombs