在c+中编译时比较复杂+;但不是在c(gcc)中 我在C++中有多重声明的问题,但C中没有。 您可以查看代码以了解更多信息

在c+中编译时比较复杂+;但不是在c(gcc)中 我在C++中有多重声明的问题,但C中没有。 您可以查看代码以了解更多信息,c++,c,gcc,compiler-errors,g++,C++,C,Gcc,Compiler Errors,G++,文件main.c #ifndef VAR #define VAR int var; #endif int main(){} 文件other.c #ifndef VAR #define VAR int var; #endif 用gcc编译 gcc main.c other.c >> success 用g编译++ g++ main.c other.c Output: /tmp/ccbd0ACf.o:(.bss+0x0): multiple definition of `var' /

文件main.c

#ifndef VAR
#define VAR
int var;
#endif
int main(){}
文件other.c

#ifndef VAR
#define VAR
int var;
#endif
用gcc编译

gcc main.c other.c
>> success
用g编译++

g++ main.c other.c
Output:
/tmp/ccbd0ACf.o:(.bss+0x0): multiple definition of `var'
/tmp/cc8dweC0.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

我的gcc和g++版本:

gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

<编译模块中全局变量的可见性在C和C++之间有细微差别。

如果这些变量是不同的变量,请在每个文件中将它们封装在匿名名称空间中

namespace {
 int var;
}
如果它们是同一个变量,其中一个需要一个
extern
decl说明符,以避免多个定义

extern int var;
您的
#define VAR
在您发布的示例中没有任何作用。定义不在编译模块中执行。

这两个
#define
指令彼此无关,因为它们位于不同的翻译单元(即源文件)中。编译器以完全隔离的方式处理这两个源文件,因此
defined(VAR)
始终为false,并且始终包含
#ifndef
的内容

如果要在多个源文件之间共享一个变量,有一种简单的方法:在一个源文件中定义它,然后在另一个源文件中声明它:

// other.cpp
int var;        // Definition.

// main.cpp
extern int var; // Declaration.
链接时,这些将引用相同的
var
。更好的方法是在标题中声明变量:

// other.h
extern int var;
然后,需要
var
的文件只需包含标题:

// main.cpp
#include "other.h"
<>你观察到C和C++之间的差异与C和C++中全局声明的标识符的处理有关。在C语言中,只要该符号的所有实际定义最终具有相同的链接和存储类,链接器可以将任意数量的暂定定义(没有存储类说明符和初始值设定项)合并到一个符号中。这是使用弱链接器符号完成的


然而,C++没有暂定定义的概念,并且将没有存储类说明符的外部声明视为定义。因此,G++生成强链接器符号,导致链接时发生冲突。

包含保护是翻译单元的本地保护。这意味着当您在一个
.cpp
文件中定义VAR时,它不会在任何其他文件中定义 var <代码>,C和C++中的代码都是形式错误的。只是这种类型的错误传统上被C编译器作为一种流行的非标准扩展而忽略了。C语言规范中甚至提到了这个扩展

J.5通用扩展插件

以下扩展在许多系统中广泛使用,但并非所有系统都可移植 实现。[……]

J.5.11多个外部定义

对象标识符可能有多个外部定义,包括或 没有明确使用关键字extern;如果定义不一致,或超过 一个已初始化,行为未定义(6.9.2)

<>但是,在C语言和C++语言中,你都有完全相同的多定义错误。让你的C编译器行为更迂腐(禁用扩展,如果它有一个选项),你的C编译器也会产生与C++编译器完全相同的错误。

再次,您的代码包含变量<代码> var > /COD>的多个定义,这是C和C++中的错误。您的

#ifdef
指令根本无法解决任何问题。预处理器指令在此无法帮助您。预处理器在每个翻译单元中本地独立工作。它无法跨翻译单元查看

如果要创建全局变量(即所有转换单元共享的同一变量),则需要对该变量进行一个且仅一个定义

int var;
在一个且仅一个翻译单元中。所有其他翻译单位应收到
var

extern int var;
后者通常放在头文件中

如果在每个翻译单元中需要一个独立变量
var
,只需在每个翻译单元中将其定义为

static int var;

(尽管C++中使用了<代码>静态< /代码>现在被无名命名空间取代了。

这很奇怪,虽然你过于复杂:VS中的cFLAGS和CPPFLAGS环境变量是什么?我已经尝试了ExtLn“C”块,但它一直无效:(我已经将
other.c
改为
other.h
g++
编译得很好。@维克多雨果,这是作弊。
g++
将把.h文件当作要预编译的头。因为main.c不包括它,所以只有一个定义。这并不能解释c和c++之间的区别“编译器进程”你是说C++在连接之前会扩展所有的γIFNDEF(αIFIFF)宏吗?@ HaangangkotEcE.是预编译程序和编译器运行在每个.cp文件上创建ObECT(.O或.OBJ)文件。然后链接器将所有的.obj文件组合成一个可执行文件。这并不能解释C和C++1之间的区别。如果您真的想确定它是定义的,请将定义(同样仅在一个翻译单元中)设为“int var=0;”。然后编译器必须将其视为一个定义。