[C言語] ポインタの派生型

### ポインタのポインタ

int main(void) {
    
    int p0 = 12345;
    int *p1;
    int **p2; // ポインタのポインタ
    int ***p3; // ポインタのポインタのポインタ
    int t1, t2, t3;

    p1 = &p0;
    p2 = &p1;
    p3 = &p2;

    t1 = *p1;
    t2 = **p2;
    t3 = ***p3;

    printf("t1=%d, t2=%d, t3=%d", t1, t2, t3);


    return 0;
}

$ gcc main.c -o main && ./main
t1=12345, t2=12345, t3=12345
全てp0の値を出力する

### 配列を指すポインタ

int main(void) {
    
    int t[3] = {1, 2, 3};
    int (*p)[3];
    int t1;

    p = &t;
    t1 = (*p)[1];
    printf("t1=%d\n", t1);

    return 0;
}

$ gcc main.c -o main && ./main
t1=2
配列は通常の配列だけでなく、ポインタも配列として表現できる

int main(void) {
    
    int a[2][3][4] = {
        {{1,2,3,4}, {5,6,7,8},{9,10,11,12}},
        {{13,14,15,16}, {17,18,19,20},{21,22,23,24}}
    };
    int *b;
    int (*c)[4];
    int (*d)[3][4];

    int a1, a2, a3;

    b = a[1][2]; // 21,22,23,24 の先頭アドレス
    c = a[1]; // {13,14,15,16}, {17,18,19,20},{21,22,23,24}の先頭アドレス
    d = a; // aの先頭アドレス

    a1 = b[3]; // 24
    a2 = c[1][2]; // 19
    a3 = d[0][1][2]; // 7 

    printf("a[1][2][3] = %d\n", a[1][2][3]); // 24
    printf("a1=%d, a2=%d, a3=%d\n", a1, a2, a3); // 24, 19, 7

    return 0;
}

$ gcc main.c -o main && ./main
a[1][2][3] = 24
a1=24, a2=19, a3=7

ポインタは配列だけでなく、連想配列としても宣言できる。
想定通りの時の高揚感が良い

int main(void) {
    
    int k1=1, k2=2, k3=3;
    int *p[3] = {&k1, &k2, &k3};
    int t;

    for (t=0; t<3; t++){
        int value = *p[t];
        printf("value=%d\n", value); // 1, 2, 3
    }

    return 0;
}

$ gcc main.c -o main && ./main
value=1
value=2
value=3
for文にしただけ

int main(void) {
    
    int k;
    char *mes[] = {"one", "two", "three", (char *) NULL};

    for(k=0; mes[k]; k++){
        printf("mes=%s, ", mes[k]); // one two three
    }

    return 0;
}

$ gcc main.c -o main && ./main
mes=one, mes=two, mes=three,

for文でmes[k]となっているので、kに値があるまでで(char *) NULLは出力されない