C中的多重定义错误

时间:2014-07-19 07:33:54

标签: c

为什么我在这里收到多个定义错误?毕竟我在两个单独的文件中使用i

//file1.c
#include <stdio.h>
#include "foo.h"
int i=700;
int main() {
    printf("in main i is %d\n", i);
    foo();
}

//file2.c
#include <stdio.h>
int i =800;
void foo() {
printf("in foo i is %d\n", i);

}

错误:

$ gcc file1.c file2.c
/tmp/ccyRgnlM.o:(.data+0x0): multiple definition of `i'
/tmp/ccoTZsnQ.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status

我正在阅读GNU C参考手册:http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Scope

我从那里引用:&#34;除非另有明确说明,否则在文件的顶层(即不在函数内)进行的声明对整个文件是可见的,包括来自函数内部,但是在文件外部不可见。&#34;

5 个答案:

答案 0 :(得分:4)

你有两个名为i的全局变量,它们相互冲突。

由于它们是两个不同的变量,因此将它们声明为static。这将把它们的范围缩小到相应的翻译单元(即源文件)。

例如:

static int i = 700;

答案 1 :(得分:2)

您不仅使用,而且i&amp;中定义全局变量file1.cfile2.c

请注意,在 C 中,变量声明定义不一样!

你有

int i=700;

int i=800;

您想要全局位置i的初始化?它不能同时是700&amp; 800,它不能定义两次。

正确的方法是拥有一个头文件myheader.h

#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
extern int i;
void foo (void);
#endif

并在每个#include "myheader.h"file1.c的开头添加file2.c声明(未定义)全局变量i并在其中定义一个文件(通常是包含main的文件,此处为file1.c):

 // file1.c
 #include <stdio.h>
 #include "myheader.h"
 int i=750;
 int main() {
   printf("in main i is %d\n", i);
   foo();
 }

您可能希望有两个不同的变量i(但出于可读性原因,请避免这样做,这是不良做法),然后在每个{{1}中声明static int i;并且不要在头文件中提及file?.c

最后,作为使用GCC的C中的初学者,总是使用所有警告和调试信息编译 ,即至少i(并改善您的代码,直到没有警告发生)。了解如何使用gcc -std=c99 -Wall -g(构建器)和make(调试器)。

答案 2 :(得分:2)

关于&#34;可见性&#34;你引用的是正式的,但需要精确的理解。特别是,您必须了解声明定义之间的区别,以及存在&#34;可见&#34;之间的区别。用于名称查找目的或用于链接目的。

您引用的声明专门讨论了声明的属性。实际上,在文件顶层创建的声明仅在该文件中可见。 &#34;可见&#34;在这种情况下意味着&#34;可见名称查找目的&#34;。

但是,如果i不仅仅是声明,那么您的声明。它们也是定义

由于它们是定义,因此它们还必须遵守管理定义的规则,例如&#34;单定义规则&#34; C语言规则说具有外部链接(变量或函数)的实体必须在整个程序中一次定义一次。对于链接目的,具有外部链接的实体始终对整个程序可见。

声明没有存储类说明符的文件级变量默认获取外部链接,即它变为全局变量。此类变量仍需要在您要使用它的每个文件中重新声明(使其在该文件中可见)。但是,您不得在任何其他翻译单元中重新定义

如果您确实希望在每个翻译单元中都有一个独立变量i,则必须确保使用内部链接声明它,即使用关键字static

答案 3 :(得分:1)

Fro全局符号,C使用平面命名空间。这意味着,不同文件中不能存在相同的全局符号,因为它们的名称相同,因此会出现多个定义链接错误。解决方案是重命名,因此它们都是唯一的,或者通过在符号前面添加static来限制范围,因此符号在本地已知为文件(更好:翻译单元)。

P.S。:符号表示标识符,可以是变量,函数,类型等。

答案 4 :(得分:0)

当你#include一个文件时,cpp(C预处理器)会直接粘贴该文件的行代替#include行,所以当你想到它时,它&# 39;显而易见的是i如何定义两次。

要执行您的预期,即创建两个名为i的单独文件范围变量(每个源文件一个),声明它们static - 这将为它们提供文件范围,并且摆脱警告。

/* file1.c */
static int i = 700;

/* file2.c */
#include "file1.c"
static int i = 800;