2012-11-25 2 views
2

두 파일이 있다고 가정합니다. file1.c- "array [10]"이라는 크기의 int 배열 10 전역 정의가 들어 있습니다. file2.c- "extern int * array"라는 이름의 int 포인터를 포함하고 있습니다.이 포인터를 배열에 연결하려고합니다.extern을 사용하여 포인터로 배열을 연결합니다.

하지만 file2.c의 file1.c 및 포인터 값의 배열 주소를 확인할 때 둘 다 다릅니다. 왜 그런가? 배열과 포인터가 같은 일을하지 않기 때문에 file2.c에서 작동하지 않습니다

답변

5

, 당신은

extern int array[]; 

이 필요합니다. 두 선언 모두 호환 유형이 있어야하며 int*int[N]과 호환되지 않습니다.

실제로 발생하는 것은 지정되지 않고 프로그램은 extern int *array;으로 잘못 구성되어 있지만 배열의 첫 번째 sizeof(int*) 바이트는 주소로 해석됩니다.

+0

하지만 실제로 메모리에서 어떻게됩니까? 배열 (40 바이트)과 포인터 (32 비트에서 4 바이트) 모두에 대해 메모리가 할당됩니까? –

+0

정의되지 않은 동작 (실제로 형식이 잘못된 프로그램). 그러나 아마, 배열의 첫 번째 네 (또는 여덟) 바이트는 주소로 해석됩니다. –

+0

괜찮지 만 링커는 포인터를 배열에 연결하며 컴파일 타임 오류는보고하지 않습니다. 실제로 연결된 것은 무엇입니까? – Azazle

1

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 <[email protected]> 
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 <[email protected]> 
804844a:  b8 00 00 00 00   mov $0x0,%eax 
804844f:  c9      leave 
8048450:  c3      ret 
,

어셈블 코드에 < -------에주의하십시오. main 함수에서 배열은 array [0]이며, test 함수에서는 배열이 주소임을 알 수 있습니다.

+0

'main'에서 주소를 출력하는 것이 아니라 포인터의 값을 출력합니다 (그리고'test'에서는'printf'에 전달 될 때 배열이 변환되는 첫 번째 요소에 대한 포인터의 값). 두 가지 모두에서'& address'를 출력하면 같은 출력을 얻게됩니다. 좋은 그림. –

관련 문제