2

Suppose I have two files: file1.c- contains global definition of an int array of size 10 named "array[10]". file2.c- contains an int pointer named "extern int *array", here I am trying to link this pointer to array.

But when I check the address of array in file1.c and pointer value in file2.c, they are both different. Why it is happening?

Azazle
  • 37
  • 1
  • 9

2 Answers2

6

That doesn't work, in file2.c, you need

extern int array[];

since arrays and pointers are not the same thing. Both declarations must have the compatible types, and int* is not compatible with int[N].

What actually happens is not specified, the programme is ill-formed with extern int *array;, but probably, the first sizeof(int*) bytes of the array are interpreted as an address.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • But what actually happens in memory? Does memory get allocated for both the array (40 bytes) and pointer (4 bytes on 32-bit)? – 1'' Nov 25 '12 at 03:17
  • Undefined behaviour (ill-formed programme, actually). But probably, the first four (or eight) bytes of teh array are interpreted as an address. – Daniel Fischer Nov 25 '12 at 03:19
  • ok, but linker links the pointer to an array and does not report a compile time error. To what it actually links? – Azazle Nov 25 '12 at 03:35
  • It links to the symbol of the same name, that means whenever you refer to `array` in `file2.c`, the appropriate number of bytes of the array are interpreted as the value of an `int*`. It is quite likely that any dereferencing of that (believed) pointer leads to a crash. – Daniel Fischer Nov 25 '12 at 03:38
0

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;
}

The output:

in main: array address = 1
in test: array address = 804a040

And the assemble code:

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   

Pay attention to the <------- in the assemble code. You can see in main function the array is array[0] and in test function the array is the address.

louxiu
  • 2,830
  • 3
  • 28
  • 42
  • In `main` you're not printing the address, but the value of the pointer (and in `test`, the value of the pointer to the first element into which the array is converted when passed to `printf`). If you print `&address` in both, you'll get the same output. Good illustration. – Daniel Fischer Nov 25 '12 at 04:00
  • int* is not compatible with int[N] – MathiasE Oct 12 '20 at 11:26