いいえ*zippo
場所15に行かないで、この場所の値を見つけます。 そうならばprintf(" * ((int **) zippo) = %p\n", * ((int **) zippo));
はprintf(" *zippo = %p\n", *zippo);
と同じものを出力しますが、そうではありません。
私はこのコードを実行すると、これは私が得るものです:
#include <stdio.h>
int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};
int main(){
printf("zippo[0] = %p\n", (void *) (zippo[0]));
printf(" zippo = %p\n", (void *) zippo);
printf(" *zippo = %p\n", (void *) (*zippo));
printf(" **zippo = %d\n", (int) (**zippo));
printf(" * ((int **) zippo) = %p\n", (void *) (* ((int **) zippo)));
}
これは私が得るものです:
zippo = 0x804a040
*zippo = 0x804a040
**zippo = 2
* ((int **) zippo) = 0x2
私は何の警告が隠されていないことを確認するためにgcc -Wall -Wextra -Wpedantic -pedantic
を使用してこのコードをコンパイルし、オプション-m32
には32ビットのアドレス(intと同じサイズ)があります。
実際に何が起こっているのか分かりにくいので、対応するアセンブリコードを見てみることにしました。 gcc -S file.c -o file.s
を使用して、以下を得る。
最初の変数宣言:
.globl zippo
.data
.align 32
.type zippo, @object
.size zippo, 32
zippo:
.long 2
.long 4
.long 6
.long 8
.long 1
.long 3
.long 5
.long 7
.section .rodata
.LC0:
.string "zippo[0] = %p\n"
.LC1:
.string " zippo = %p\n"
.LC2:
.string " *zippo = %p\n"
.LC3:
.string " **zippo = %d\n"
.LC4:
.string " * ((int **) zippo) = %p\n"
correcspondingアセンブリprintf("zippo[0] = %p\n", (void *) (zippo[0]));
用:
movl $zippo, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
correcspondingアセンブリprintf(" zippo = %p\n", (void *) zippo);
用:
movl $zippo, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
printf(" *zippo = %p\n", (void *) (*zippo));
ためcorrecspondingアセンブリ
movl $zippo, %esi
movl $.LC2, %edi
movl $0, %eax
call printf
printf(" **zippo = %d\n", (int) (**zippo));
ためcorrecspondingアセンブリ:
movl $zippo, %eax
movl (%rax), %eax
movl %eax, %esi
movl $.LC3, %edi
movl $0, %eax
call printf
correcspondingアセンブリprintf(" * ((int **) zippo) = %p\n", (void *) (* ((int **) zippo)));
movl $zippo, %eax
movq (%rax), %rax
movq %rax, %rsi
movl $.LC4, %edi
movl $0, %eax
call printf
ためのあなたがここに気づくことができるように、3最初のprintfのために、対応するアセンブリがexactely同じです(フォーマットに対応するLCxはどのような変更ですか)。 最後の2つのprintfと同じことです。
zippo
が2次元配列であることをコンパイラが認識しているので、*zippo
は、最初の要素のアドレスからデータが始まる1次元配列です。
ギザギザの配列(int **のようなもの)については、すでに何百もの質問があります。なぜ完全に異なるタイプが使用されると思いますか? 'int'を持っていれば' _Complex'を 'printf'できません! – Olaf