为什么我在这里收到多个定义错误?毕竟我在两个单独的文件中使用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;
答案 0 :(得分:4)
你有两个名为i
的全局变量,它们相互冲突。
由于它们是两个不同的变量,因此将它们声明为static
。这将把它们的范围缩小到相应的翻译单元(即源文件)。
例如:
static int i = 700;
答案 1 :(得分:2)
您不仅使用,而且在i
&amp;中定义全局变量file1.c
。 file2.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;