gpt4 book ai didi

c - 了解标识符的链接

转载 作者:太空宇宙 更新时间:2023-11-04 06:12:25 24 4
gpt4 key购买 nike

我正在阅读 the Standard : N1570并遇到了一些误解。我写了下面这个简单的例子:

test.h:

#ifndef TEST_H
#define TEST_H

extern int second;

#endif //TEST_H

test.c:

#include "test.h"

enum test_enum{
first,
second
};

但是编译失败,报错:

error: ‘second’ redeclared as different kind of symbol
second
^~~~~~

这很奇怪,因为部分 6.4.4.3#2 指定:

2 An identifier declared as an enumeration constant has type int.

在我们的案例中,枚举常量具有文件范围,因此我希望它能够正常编译。

我把上面的例子重写如下:main.c:

extern int second;
int main(int argc, char const *argv[])
{
printf("Second: %d\n", second);
}

现在链接器提示:

undefined reference to `second'

为什么?它应该在 test.c 中找到定义,因为正如 Section 6.2.2#5 指定的那样:

If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

最佳答案

对象和常量是不同的东西

你对 6.4.4.3 2 的引用,枚举常量的类型为 int , 建议你认为因为 extern int secondenum { second }申报second成为int , 这两个声明 second可能指的是同一件事。这是不正确的。

extern int second声明 second成为一个对象(内存区域)的名称,该对象将保存 int . enum { second }声明 second成为具有特定值的枚举常量。枚举常量没有与之关联的对象(没有内存)。一个int对象和 int常量是不同的东西,您不能在同一范围内对它们使用相同的标识符。

并非所有声明都是定义

关于您关于链接错误的问题,“未定义对‘second’的引用”,虽然test.c可能包含 external int second (因为它由包含的 test.h 提供,这不是 second 的定义。它只是一个声明,它告诉编译器该名称引用一个对象。它没有定义对象。或者,如果test.c 包含 enum { second } ,这只是将 second 声明为常量。它没有定义对象。

由于编程语言发展的历史,关于什么是定义的规则有点复杂。对于在文件范围内声明的对象的标识符,基本上有四种情况:

  • 带有 extern 的声明只是声明,不是定义。示例:extern int second; .
  • 带有初始值设定项的声明是一个定义。示例:int second = 2; .
  • 没有extern的声明没有初始值设定项是一个暂定定义。如果翻译单元(正在编译的源文件,包含所有包含的文件)中没有出现定义,则暂定定义成为定义。示例:int second; .

链接在这里没有帮助。 extern int secondtest.cextern int secondmain.c由于链接,可能引用同一个对象,但没有定义它们引用的对象。或者,换句话说,如果 test.c包含 enum { second } , 那么它不会定义名为 second 的对象, 所以没有 extern int second 的对象在 main.c可以引用。

关于c - 了解标识符的链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53568087/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com