sizeof
または 単項演算子のオペランドである場合、または宣言で別の配列を初期化するために使用される文字列リテラルである場合を除いて&
、型 "N 要素配列 " の式は次の式T
に変換 ("decay") されます。 「ポインタT
」と入力すると、式の値が配列の最初の要素のアドレスになります。
宣言を仮定して
char ma[5][30];
その場合、次のすべてが真です。
式のma
型は「30 要素配列の 5 要素配列char
」です。がまたは unaryma
のオペランドでない限り、 「またはの 30 要素配列へのポインタ」型の式に変換され、その値は配列の最初の要素のアドレスまたは になります。sizeof
&
char
char (*)[30]
&ma[0]
式のma[i]
型は「30 要素配列char
」です。がまたは unaryma[i]
のオペランドでない限り、型「ポインタ」またはの式に変換され、その値は配列の最初の要素のアドレスまたは になります。 sizeof
&
char
char *
&ma[i][0]
式のma[i][j]
型はchar
です。
式の型は、「 、または&ma
の 30 要素配列の 5 要素配列へのポインタ」です。 char
char (*)[5][30]
式の&ma[i]
型はchar (*)[30]
です。
式の&ma[i][j]
型はchar *
です。
式、、、、およびの値はすべて同じです。配列のアドレスは、配列の最初の要素のアドレスと同じです。 ma
&ma
ma[0]
&ma[0]
&ma[0][0]
タイプchar (*)[30]
とは、 、または相互に互換性がchar (*)[5][30]
ないことに注意してください。これらの型の値を type の変数に割り当てたい場合は、 などの明示的なキャストを使用する必要があります。 char *
char *
char *p = (char *) ma;
編集
タイプは重要です。ポインター演算は、ポイント先の型に基づいているため、式 likeは、ポイント先ptr+1
の型に基づいて異なる結果を返します。ptr
例えば:
#include <stdio.h>
int main( void )
{
char ma[5][30] = {{0}};
char (*p0)[5][30] = &ma;
char (*p1)[30] = &ma[0];
char *p2 = &ma[0][0];
printf("%5s%-15s%-15s\n"," ","ptr","ptr+1");
printf("%5s%-15s%-15s\n"," ","-----","-----");
printf("%-5s%-15p%-15p\n","p0", (void *) p0, (void *) (p0+1));
printf("%-5s%-15p%-15p\n","p1", (void *) p1, (void *) (p1+1));
printf("%-5s%-15p%-15p\n","p2", (void *) p2, (void *) (p2+1));
return 0;
}
異なるタイプの 3 つのポインターを作成します。p0
は 型char (*)[5][30]
で の結果を受け取り、&ma
はp1
型char (*)[30]
で の結果を受け取り、&ma[0]
はp2
型char *
で の結果を受け取ります&ma[0][0]
。次に、各ポインターの値に 1 を加えた値よりも、各ポインターの値を出力します。結果は次のとおりです。
ptr ptr+1
----- -----
p0 0x7fff36670d30 0x7fff36670dc6
p1 0x7fff36670d30 0x7fff36670d4e
p2 0x7fff36670d30 0x7fff36670d31
各ポインターは同じ値で始まりますが、ポインターに 1 を追加すると、型に基づいて異なる結果が得られます。 p0
の 5x30 要素配列を指すchar
ためp0 + 1
、 の次の 5x30 要素配列の先頭を指しchar
ます。 p1
の 30 要素配列を指しているchar
ため、 ( )p1 + 1
の次の 30 要素配列を指しています。最後に、単一の を指すため、次の文字 ( ) を指します。 char
ma[1]
p2
char
p2 + 1
ma[0][1]