简体   繁体   English

C语言中的多定义错误

[英]Multiple definition error in C

Why am I getting multiple definition error here? 为什么在这里出现多定义错误? After all I am using i in two separate files. 毕竟,我在两个单独的文件中使用了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);

}

Error: 错误:

$ 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

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

and I quote from there: "Unless explicitly stated otherwise, declarations made at the top-level of a file (ie, not within a function) are visible to the entire file, including from within functions, but are not visible outside of the file." 我从那里引用:“除非另有明确说明,否则在文件顶层(即不在函数内)进行的声明对整个文件都是可见的,包括从函数内可见,但在文件外部不可见”。

You have two global variables called i , and they clash with each other. 您有两个名为i全局变量,它们相互冲突。

Since they are two distinct variables, declared them as static . 由于它们是两个不同的变量,因此将它们声明为static This will reduce their scope to the corresponding translation unit (ie source file). 这会将它们的范围缩小到相应的翻译单元(即源文件)。

For example: 例如:

static int i = 700;

You are not only using but you are defining global variable i in both file1.c & file2.c 您不仅在使用而且还在file1.cfile2.c定义全局变量i

Notice that in C a variable declaration is not the same as a definition ! 注意,在C中 ,变量声明定义不同

You have 你有

int i=700;

and

int i=800;

What initialization of global location i do you want? 什么初始化全局位置的i你想要什么? It cannot be both 700 & 800 and it cannot be defined twice. 它不能同时为700和800,并且不能定义两次。

The correct way would be to have a header file myheader.h : 正确的方法是拥有头文件myheader.h

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

and add #include "myheader.h" at start of each file1.c and file2.c to declare (not define) a global variable i and define it in one single file (often the one containing main , here file1.c ) : 并在每个file1.cfile2.c开头添加#include "myheader.h" ,以声明 (未定义)全局变量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();
 }

You might want to have two different variables i (but avoid doing that, this is bad practice for readability reasons), then declare static int i; 您可能希望拥有两个不同的变量i (但要避免这样做,出于可读性原因,这是一种不好的做法 ),然后声明static int i; in each file?.c and don't mention i in the header file. 在每个file?.c ,不要在头文件中提及i

At last, as a beginner in C using GCC , always compile with all warnings and debug info ie with at least gcc -std=c99 -Wall -g (and improve your code till no warning happens). 最后,作为使用GCC的 C初学者,请始终编译所有警告并调试信息,即至少使用gcc -std=c99 -Wall -g (并改进您的代码,直到没有警告发生为止)。 Learn how to use make (the builder) and gdb (the debugger). 了解如何使用make (生成器)和gdb (调试器)。

The statement about "visibility" you quoted is formally correct, but requires precise understanding. 您引用的有关“可见性”的声明在形式上是正确的,但需要准确理解。 In particular, you have to understand the difference between declarations and definitions , as well as the difference between being "visible" for name lookup purposes or for linkage purposes. 特别是,您必须了解声明定义之间的区别,以及为了名称查找链接目的而“可见”之间的区别。

The statement you quoted specifically talks about properties of declarations . 您引用的语句专门讨论了声明的属性。 Indeed, a declaration made at the top level of the file is only visible within that file. 实际上,在文件的顶层进行的声明仅在该文件中可见。 "Visible" in this case means "visible for name lookup purposes ". 在这种情况下,“可见”表示“出于名称查找目的可见”。

However, your declarations if i are more than just declarations. 但是,如果i不只是声明,那么您的声明。 They are definitions as well. 它们也是定义

And since they are definitions, they also have to obey the rules that govern definitions , like "one-definition rule" of C language. 并且由于它们是定义,因此它们还必须遵守管理定义的规则,例如C语言的“一定义规则”。 The rule says that entities with external linkage (variables or functions) have to be defined once and only once in the entire program. 该规则指出,在整个程序中,必须仅一次定义具有外部链接(变量或函数)的实体。 For linkage purposes entities with external linkage are always visible to the entire program. 出于链接目的,具有外部链接的实体始终对整个程序可见。

A file-level variable declared without storage class specifier acquires external linkage by default, ie it becomes a global variable. 在没有存储类说明符的情况下声明的文件级变量默认情况下会获得外部链接,即它成为全局变量。 Such variable still needs to be redeclared in each file where you want to use it (to make it visible in that file). 仍需要在每个要使用该文件的文件中重新声明该变量(以使其在该文件中可见 )。 However, you are not allowed to redefine it in any other translation unit. 但是,不允许在任何其他翻译单元中重新定义它。

If you really want to have an independent variable i in each translation unit, you have to make sure you declare it with internal linkage, ie with keyword static . 如果您确实希望每个翻译单元中都有一个自变量i ,则必须确保使用内部链接(即,使用关键字static声明它。

Fro global symbols, C uses flat namespace. 对于全局符号,C使用平面名称空间。 That means, there cannot be the same global symbol in different files since their name will be the same and thus, multiple definition linking error occurs. 这意味着,不同的文件中不能存在相同的全局符号,因为它们的名称将相同,因此会发生多定义链接错误。 The solution is to either rename so they're all unique, or limit the scope by prefixing the symbol with static , so the symbol is known locally to the file (better: translation unit) only. 解决方案是要么重命名它们都是唯一的,要么通过在符号前面加上static限制范围,因此该符号仅在文件中本地可用(更好的是:翻译单元)。

PS: Symbol means identifier, it can be variable, function, type, etc. PS:符号表示标识符,可以是变量,函数,类型等。

When you #include a file, cpp (the C pre-processor) literally pastes the lines of that file in place of the #include line, so when you think of it that way, it's obvious to see how i has been defined twice. 当您#include一个文件时,cpp(C预处理程序)从字面上粘贴该文件的行代替#include行,因此当您以这种方式考虑时,很明显地看到i是如何被定义两次的。

To do what you intended, ie, to create two separate file-scoped variables called i (one for each source file), declare them static --this will give them file scope, and get rid of the warning. 要执行您的意图,即创建两个单独的文件范围的变量,称为i (每个源文件一个),将它们声明为static这将为它们提供文件范围,并摆脱警告。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM