【问题标题】:using extern to link array with pointer使用 extern 将数组与指针链接起来
【发布时间】:2012-11-25 03:11:47
【问题描述】:

假设我有两个文件: file1.c- 包含一个名为“array[10]”的大小为 10 的 int 数组的全局定义。 file2.c- 包含一个名为“extern int *array”的 int 指针,这里我试图将这个指针链接到数组。

但是当我检查 file1.c 中的数组地址和 file2.c 中的指针值时,它们都是不同的。为什么会这样?

【问题讨论】:

    标签: c arrays pointers extern


    【解决方案1】:

    那不行,在file2.c,你需要

    extern int array[];
    

    因为数组和指针不是一回事。两个声明必须具有兼容的类型,int*int[N] 不兼容。

    没有具体说明实际发生的情况,程序格式错误,extern int *array;,但可能数组的前 sizeof(int*) 字节被解释为地址。

    【讨论】:

    • 但是内存中到底发生了什么?是否为数组(40 字节)和指针(32 位为 4 字节)分配了内存?
    • 未定义的行为(实际上是格式错误的程序)。但很可能,数组的前四个(或八个)字节被解释为一个地址。
    • 好的,但是链接器将指针链接到一个数组并且不报告编译时错误。它实际链接到什么?
    • 它链接到同名符号,这意味着每当您在file2.c 中引用array 时,数组的适当字节数将被解释为int* 的值.对该(相信的)指针的任何取消引用很可能会导致崩溃。
    【解决方案2】:

    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   
    

    注意汇编代码中的

    【讨论】:

    • main 中,您打印的不是地址,而是指针的值(在test 中,指针的值指向数组在传递时转换为的第一个元素到printf)。如果您在两者中都打印&amp;address,您将获得相同的输出。很好的插图。
    • int* 与 int[N] 不兼容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多