【问题标题】:Bad linkage of `char *array[size]` and `extern char **array`?`char *array[size]` 和 `extern char **array` 的链接错误?
【发布时间】:2012-06-03 21:38:19
【问题描述】:

首先,看这个例子(我是为了例子而编造的,它不是一个真正的程序):

随便.h

#ifndef WHATEVER_H
#define WHATEVER_H

void fill(void);

#endif

main.c

#include <stdio.h>
#include "whatever.h"

char *names[10] = {NULL};

int main()
{       
        int i; 
        fill(); 
        for (i = 0; i < 10; ++i)
                printf("%s\n", names[i]);
        return 0;
}

whatever.c

#include "whatever.h"

extern char **names;

void fill(void)
{
        int i;
        for (i = 0; i < 10; ++i)
                names[i] = "some name";
}

当我使用:

gcc -o test main.c whatever.c -Wall -g

我没有收到任何错误或警告。但是,当我运行程序时,我看到在fill 中,names 实际上是NULL。如果在whatever.c我改了

extern char **names;

extern char *names[];

那么一切都很好。

谁能解释为什么会这样?如果 gcc 无法将extern char **names;main.c 中的那个链接,它不应该给我一个错误吗?如果它可以链接它们,names 怎么会在whatever.c 中变成NULL

另外,extern char **names;extern char *names[]; 有何不同?


我在 Linux 下使用 gcc 4.5.1 版。

更新

为了进一步调查,我将main.cnames 的定义更改为:

char *names[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};

(在whatever.c 中保留extern char **names;)和gdb,我可以看到names 有一个值。如果我将该值转换为char * 并打印它,它会给我"1"。 (注意,不是*names"1",而是(char *)names

基本上,这意味着 gcc 以某种方式设法将whatever.c 中的extern char **names;main.c 中的names[0] 链接起来!

【问题讨论】:

  • 有人可以用其他编译器(或更新版本的 gcc)测试这个吗?
  • @RichardJ.RossIII,我刚刚意识到(并检查)链接器不检查类型兼容性,现在我认为这是完全有道理的。
  • @Bo:不是重复的。这个问题是关于 指针数组 与指向指针的指针;您链接到的问题是关于 指向数组的指针 与指向指针的指针。
  • @BoPersson,感谢您的链接。它解决了我 8 年来显然犯错的一些问题。

标签: c gcc linkage


【解决方案1】:

当您在不同的编译单元中为同一个变量使用不同的、不兼容的类型时(就像您在此处所做的那样),您会得到未定义的行为。这意味着它可能无法正常工作,并且您可能不会收到任何有关它的错误或警告消息。

为什么会发生这种情况(以及为什么规范说这是未定义的)是由于大多数链接器的工作方式。大多数链接器对类型一无所知。他们只了解名字和记忆。所以就链接器而言,变量只是从某个地址开始的一块内存。在您的(原始)程序中,main.cnames 定义为指一个足够大的内存块的开始,以容纳 10 个指针(可能是 40 或 80 字节,具体取决于这是 32 位还是 64 位系统),所有这些都是NULL。另一方面,whaterver.c 假定 names 指的是一个足够大的内存块以容纳 ONE 指针,并且该指针指向一个由 10 个指针组成的数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    • 2021-09-28
    • 2015-06-07
    • 1970-01-01
    • 2017-12-23
    • 2015-06-04
    • 2021-08-24
    相关资源
    最近更新 更多