少し分解して、コードの各行について次のように説明できることを見てみましょう。
int main (void){
char buf[4096 + 1];
を宣言するchar[4097]と、通常、 が入力されたときにスタック ポインターを調整してスタックに割り当てられますmain。配列の内容は不定です。
printf("(unsigned) buf %d\n", (unsigned) buf);
&配列型の式は、それがアドレス ( )sizeofまたは演算子のオペランドでない限り_Alignof、または文字配列の初期化に使用される文字列リテラルでない限り、配列の最初の要素へのポインターに変換されます (6.3.2.1 p. 3 )、その行はと同等です
printf("(unsigned) buf %d\n", (unsigned) &buf[0]);
の最初のバイトのアドレスを取得しbuf、それを に変換してunsigned、結果の数値を符号付き整数として出力します。unsigned結果の値が として表現できない場合、動作は未定義であることに注意してくださいint。&buf[0]へのポインターの変換unsignedは実装定義であり、未定義の動作を引き起こす可能性があります (6.3.2.3 p. 6)。通常、sizeof(unsigned)ポインター値のバイトは符号なし整数として解釈されます (通常、ポインターのサイズが のサイズよりも小さくないことが含まれますunsigned)。あなたの場合、結果は
(unsigned) buf 2268303
印刷されました。次
doing();
それでは、見てみましょうdoing:
void doing(){
char buf[4096 + 1];
もう 1 つchar[4097]は宣言されています。通常は、doing入力時にスタック ポインターを調整することによって割り当てられます。この配列の内容も不確定です。
printf("buf %d\n", buf);
繰り返しますbufが、 type の式は、つまりにchar[4097]変換され、引数が必要な に渡されます。型の不一致は未定義の動作を引き起こします。通常、ポインター値のバイトは符号付き整数として解釈されます。結果は出力ですchar*&buf[0]printfintsizeof(int)
buf 2264159
bufこれは、 indoingが から 4144 バイト離れて割り当てられmain、スタックが下向きに成長することを強く示唆しています。
printf("buf %f\n", buf);
もう一度、配列からポインターへの変換がありprintf、double引数が必要ですが、char*. より未定義の動作、明示は次のとおりです
buf 0.000000
印刷されます。それがどうなるかは、一般的には答えられません (結局のところ、未定義の動作です)。64 ビット システムでは、一般的な動作はprintf、ポインターまたは整数型の引数が汎用レジスターで渡され、浮動小数点引数が浮動小数点レジスターで渡されることです。そのため、printfたまたま 0 の値が含まれている浮動小数点レジスタが読み取られます。
printf("buf %d\n", (unsigned) buf);
この行は の対応する行と同じセマンティクスを持っていますがmain、別の arraybufであるため、変換から得られる (符号なし) 整数は異なります。
buf 2264159
printfの最初のものと同じものを出力しますがdoing、これは驚くべきことではありません (ただし、未定義の動作が関係しているため、保証されません)。
printf("buf %s\n", buf+2);
bufが に変換され&buf[0]、それに 2 が加算されて になり&buf[2]ます。これは に渡されprintf、%s変換により、 の 0 で終わる配列へのポインタがchar引数として期待されます。これは、の 2 番目の引数の型が、変換指定子により期待される型と正確に一致する、printfプログラム全体で唯一の呼び出しです。printfただし、 の内容bufは不定であるため、配列に 0 バイトがないと、 による無効な読み取りが発生しますprintf。しかし、どうやらbuf[2]0 だったので、
buf
印刷されました。
printf("buf %d\n", buf+2);
buf + 2は再び に評価され、それは が期待する&buf[2]場所に渡されます。型の不一致は未定義の動作を引き起こしますが、出力はprintfint
buf 2264161
は何も悪いことが起きていないことを示しており、&buf[2]は 2 バイト遅れているため、出力&buf[0]される数値はdoingの最初ので出力される数値よりも 2 大きくなりprintfます。
}
に戻るmain:
printf("(unsigned) buf %d\n", (unsigned) buf);
その行は の最初のprintf呼び出しと同じmainであるため、上記で説明したのと同じセマンティクスを持ちます。
(unsigned) buf 2268303
そして同じ出力を生成します。
return 0;
}