動機
C言語での変数宣言に、一貫性を発見したので書きたいと思います
宣言の一貫した規則を示すために、いくつかの種類の変数宣言を見ていきたいと思います
変数宣言の一貫性
その発見とは***「変数の宣言」は「その変数の特有のアクセス方法」に似せた構文***になっているということです
配列
int array[10];
printf("%d\n", array[2]);
まとめると、
宣言 | アクセス方法 |
---|---|
array[10] |
array[2] |
宣言とアクセス方法が似ていることが分かります。
ポインタ
int *p;
printf("%d\n", *p);
ポインタの特有の使い方は「*」を使ってポインタの指している値にアクセスすることだと思います。このアクセス方法がポインタの宣言に反映されていると考えられます
以前の私はint* p
と書いてintポインタ型のp
と解釈していましたが、これでは以下の結果の説明がつかないです。
/* qはただのint型でintのポインタ型ではない */
int* p, q;
まとめると、
宣言 | アクセス方法 |
---|---|
*p |
*p |
「配列」と「ポインタ」だけでは「「変数の宣言」は「その変数の特有のアクセス方法」に似せた構文」と言い切れないので、「配列へのポインタ」と「関数へのポインタ」見てみます
配列へのポインタ
int (*arp)[10];
アドレスを入れるときは以下のように入れます。
int array_ten[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
arp = &array_ten;
以下の書き方でarray_ten[3]と同じ要素にアクセスします
printf("%d\n", (*arp)[3]); // 4
まとめると、
宣言 | アクセス方法 |
---|---|
(*arp)[10] |
(*arp)[3] |
宣言とアクセス方法、似ていませんか?
関数ポインタ
int (*funp)(int, int);
アドレスを入れるときは以下のようにします
// a + bをしてintで返す
int add(int a, int b){
return a + b;
}
// addのアドレスを代入できる
funp = &add;
printf("%d\n", (*funp)(1, 2)); // 3
まとめると、
宣言 | アクセス方法 |
---|---|
(*funp)(int,int) |
(*funp)(1,2) |
まとめ
以上を踏まえるとC言語の変数の宣言とアクセス方法はとても良く似ています。私の憶測ではありますが、アクセス方法に似せた宣言というのが、C言語にある一貫した宣言の記法なのだと思います。
今までできた宣言に勢揃いしてもらうと、以下みたいになります
int *p, array[10], (*arp)[10], (*funp)(int, int);
上のC言語の宣言のp
, array
, arp
, funp
の解釈が前より変わって見えませんか?