`的char *数组[尺寸]`和`的extern焦炭的坏联动** array`? [英] Bad linkage of `char *array[size]` and `extern char **array`?

查看:171
本文介绍了`的char *数组[尺寸]`和`的extern焦炭的坏联动** array`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,看看这个例子(我做这件事为例的缘故,它不是一个真正的程序):

First, see this example (I made this up for the sake of example, it's not a real program):

whatever.h

whatever.h

#ifndef WHATEVER_H
#define WHATEVER_H

void fill(void);

#endif

的main.c

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

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

我没有得到任何错误或警告。然而,当我运行程序时,我看到,在填写名称其实就是 NULL 。如果 whatever.c 更改

extern char **names;

extern char *names[];

然后一切都很好。

then everything is fine.

谁能解释为什么出现这种情况?如果GCC不能链接的extern字符**名; 与一个在的main.c ,应该不会吧给我一个错误?如果可以链接它们,如何来名称 whatever.c <最终被 NULL / code>?

Can anyone explain why this happens? If gcc couldn't link extern char **names; with the one in main.c, shouldn't it have given me an error? If it could link them, how come names ends up being NULL in whatever.c?

此外,请问的extern字符**名; 不同于的extern的char *名称[];

我使用Linux下的gcc版本4.5.1。

I am using gcc version 4.5.1 under Linux.

要进一步研究这个问题,我换名称的定义的main.c 来:

To further investigate this, I change the definition of names in main.c to:

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

(保持的extern字符**名; whatever.c )和 GDB ,我可以看到名称有一个值。如果我投这个值的char * 并打印,它给了我1。 (需要注意的是,这不是 *名称1,但(字符* )名称

(keeping extern char **names; in whatever.c) and with gdb, I can see that names has a value. If I cast that value to char * and print it, it gives me "1". (Note that, it's not *names that is "1", but (char *)names)

基本上,它的意思是,海湾合作委员会已总算链接的extern字符**名; whatever.c 名称[0] 的main.c

Basically, what it means is that gcc has somehow managed to link extern char **names; in whatever.c with names[0] in main.c!

推荐答案

当你使用不同的,不兼容的类型在不同的编译单元相同的变量(如你在这里做),你得到了一个未定义的行为。这意味着它可能不会工作,你可能不会得到关于它的任何错误或警告消息。

Whenever you use different, incompatible types for the same variable in different compilation units (as you have done here), you get undefined behavior. That means it probably won't work and you may not get any error or warning messages about it.

为什么发生这种情况(以及为什么规范说这是不确定的),是由于这样大多数的连接器工作。大多数的连接器不理解什么类型;他们只知道名字和内存。所以,只要连接器而言,一个变量只是一个起始于一些地址的存储块。在你(原)方案的main.c 定义名称为指的内存大块的起始足够保持10指针(大概40或80个字节,这取决于是否这是一个32位或64位系统),所有这些都为NULL。 whaterver.c ,在另一方面,假定名称指的是大内存块足以容纳一个指针,而指针指向在10指针数组。

WHY this happens (and why the spec says this is undefined) is due to the way most linkers work. Most linkers don't understand anything about types; they only understand names and memory. So as far as the linker is concerned, a variable is just a block of memory starting at some address. In your (original) program main.c defines names as referring to the start of a block of memory big enough to hold 10 pointers (probably 40 or 80 bytes, depending on whether this is a 32-bit or 64-bit system), all of which are NULL. whaterver.c, on the other hand, assumes that names refers to a block of memory big enough to hold ONE pointer, and that pointer points at an array of 10 pointers.

这篇关于`的char *数组[尺寸]`和`的extern焦炭的坏联动** array`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆