2 つのファイルがあるとします: file1.c-「array[10]」という名前のサイズ 10 の int 配列のグローバル定義が含まれています。file2.c-「extern int *array」という名前のintポインターが含まれています。ここでは、このポインターを配列にリンクしようとしています。
しかし、file1.c の配列のアドレスと file2.c のポインター値を確認すると、どちらも異なっています。なぜそれが起こっているのですか?
それはうまくいきません、でfile2.c
、あなたが必要です
extern int array[];
配列とポインタは同じものではないためです。両方の宣言には互換性のある型が必要であり、 とint*
は互換性がありませんint[N]
。
実際に何が起こるかは指定されていません。プログラムの形式が正しくありませんextern int *array;
が、おそらく、sizeof(int*)
配列の最初のバイトがアドレスとして解釈されます。
extern1.c
#include <stdio.h>
extern int *array;
int test();
int main(int argc, char *argv[])
{
printf ("in main: array address = %x\n", array);
test();
return 0;
}
extern2.c
int array[10] = {1, 2, 3};
int test()
{
printf ("in test: array address = %x\n", array);
return 0;
}
出力:
in main: array address = 1
in test: array address = 804a040
そして、アセンブル コード:
08048404 <main>:
8048404: 55 push %ebp
8048405: 89 e5 mov %esp,%ebp
8048407: 83 e4 f0 and $0xfffffff0,%esp
804840a: 83 ec 10 sub $0x10,%esp
804840d: 8b 15 40 a0 04 08 mov 0x804a040,%edx <--------- this (1)
8048413: b8 20 85 04 08 mov $0x8048520,%eax
8048418: 89 54 24 04 mov %edx,0x4(%esp)
804841c: 89 04 24 mov %eax,(%esp)
804841f: e8 dc fe ff ff call 8048300 <printf@plt>
8048424: e8 07 00 00 00 call 8048430 <test>
8048429: b8 00 00 00 00 mov $0x0,%eax
804842e: c9 leave
804842f: c3 ret
08048430 <test>:
8048430: 55 push %ebp
8048431: 89 e5 mov %esp,%ebp
8048433: 83 ec 18 sub $0x18,%esp
8048436: c7 44 24 04 40 a0 04 movl $0x804a040,0x4(%esp) <------- this (2)
804843d: 08
804843e: c7 04 24 3d 85 04 08 movl $0x804853d,(%esp)
8048445: e8 b6 fe ff ff call 8048300 <printf@plt>
804844a: b8 00 00 00 00 mov $0x0,%eax
804844f: c9 leave
8048450: c3 ret
アセンブル コードの <--------- に注意してください。メイン関数では配列が array[0] であり、テスト関数では配列がアドレスであることがわかります。