【发布时间】: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.c 中names 的定义更改为:
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 年来显然犯错的一些问题。