在C中得到一个“'X' first defined here '的多个定义”错误,尽管我只定义了X一次

atmip9wb  于 2023-01-04  发布在  其他
关注(0)|答案(1)|浏览(781)

在我的所有文件中,名称"codes"只有一个定义,尽管我仍然得到一个错误。我尝试使用pragma一次和ifndef,但没有效果。
下面是我得到的错误:

marcin@marcin-VirtualBox:~/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2$ make
gcc -g checkCode.o getDigitBase10.o main.o populateCodeList.o getNextGuess.o -o solve -lm
/usr/bin/ld: getDigitBase10.o:/home/marcin/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2/funkcje.h:10: multiple definition of `codes'; checkCode.o:/home/marcin/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2/funkcje.h:10: first defined here
/usr/bin/ld: main.o:/home/marcin/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2/funkcje.h:8: multiple definition of `codes'; checkCode.o:/home/marcin/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2/funkcje.h:10: first defined here
/usr/bin/ld: populateCodeList.o:/home/marcin/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2/funkcje.h:8: multiple definition of `codes'; checkCode.o:/home/marcin/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2/funkcje.h:10: first defined here
/usr/bin/ld: getNextGuess.o:/home/marcin/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2/funkcje.h:8: multiple definition of `codes'; checkCode.o:/home/marcin/Pulpit/INA/Wstęp/Laby/Lista 4/zadanie 2/funkcje.h:10: first defined here
collect2: error: ld returned 1 exit status
make: *** [Makefile:10: all] Błąd 1

这是我所有的档案
一个一个一个一个一个一个x一个一个二个一个x一个一个三个一个x一个一个x一个一个x一个一个
我试着使用一次pragma来避免链接器错误,并尝试以ifndef顺序包围代码定义,但它仍然产生与以前相同的错误。当复制和粘贴所有内容到同一个文件时,没有抛出任何错误。

xqnpmsa8

xqnpmsa81#

在文件作用域中,int codes[SIZE]是一种特殊的声明,称为 tentative definition。尽管它的名称是这样,但它不是一个定义。然而,它可以导致创建一个定义。
声明和定义在多个翻译单元中使用的对象的一种简洁方法是在标头中使用extern声明该对象,标头包含在按名称使用该对象的每个单元中:

extern int codes[SIZE];

并在一个翻译单元的源文件中定义该对象:

int codes[SIZE] = { 0 };

不带extern的试探性定义形式已经在某种程度上得到了普遍使用,特别是在GCC中,GCC将其视为“通用”符号,如下所述。然而,GCC的默认行为在版本10中发生了变化,结果是这种常见做法现在会导致多定义错误。您可以使用-fcommon开关获得旧的行为,但一般来说,程序员应该切换到显式声明形式extern codes[SIZE];
int codes[SIZE];的文件范围声明是一个试探性定义的原因在于C语言的发展历史。C语言并不是事先完全规划和设计的。它是通过实验和不同地方的不同人不同地实现事情来发展的。当C委员会标准化C语言时,它们必须处理不同的做法和执行情况。一种常见的做法是声明多个单元中的int i;,目的是创建单个i。(这种行为是从FORTRAN继承而来的,FORTRAN有一个类似的特性,即公共对象。)
为了适应这一点,委员会将文件作用域中的int i;描述为一种特殊的声明,一种临时定义。如果在同一翻译单元中存在定义同一标识符的规则定义,则临时定义充当普通声明,而不是定义。如果没有规则定义,编译器(或C实现的其它部分)创建标识符的定义,就好像它已经用零初始化一样。
C标准将多个试验性定义的协调留给每个C实现;没有定义int i;在多个翻译单元中使用时的行为,10版之前GCC默认行为是使用“公共符号”行为;当链接时,多个试验性定义将被调和为单个定义。(为了支持这一点,编译器在创建对象模块时将临时定义与常规定义标记为不同,以便链接器知道哪个是哪个。)在版本10中,默认值发生了变化,和GCC现在将从暂定定义中得到的定义视为常规符号而不是通用符号。这就是为什么您会得到“头文件中包含int codes[SIZE];导致“多重定义”错误。

相关问题