Hard to compile in C ++, but not in c (gcc)

I have a problem with multiple declarations in C ++, but not in c. You can see the code for more information.

main.c file

#ifndef VAR #define VAR int var; #endif int main(){} 

file other.c

 #ifndef VAR #define VAR int var; #endif 

Compile with gcc

 gcc main.c other.c >> success 

Compile with 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 

My version of gcc and 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. 
+6
source share
4 answers

Your code is formally incorrect for both C and C ++ due to the many definitions of the var variable. It's just that this type of error is traditionally ignored by C compilers as a popular custom extension. This extension is even mentioned in the C language specification.

J.5 General extensions

The following extensions are widely used in many systems, but not portable for all implementations. [...]

J.5.11 Several external definitions

There may be more than one external definition for an object identifier, with or without explicit use of the extern keyword; if the definitions do not match or more than one is initialized, the behavior is undefined (6.9.2).

But formally, you have exactly the same multiple definition error in both C and C ++. Ask your C compiler to be more pedantic (disable extensions if it has an option for this), and your C compiler should also generate the same error as your C ++ compiler.

Again, the code contains several definitions of the var variable, which is an error in both C and C ++. Your #ifdef directives do not solve anything. The teachers cannot help you here. The preprocessor operates locally and independently in each translation unit. He cannot see the translation unit.

If you want to create a global variable (i.e. the same variable shared by all translation units), you need to make one and only one definition of this variable

 int var; 

in one and only one translation unit. All other translation units must receive non-def declarations var

 extern int var; 

The latter is usually placed in the header file.

If you need a separate independent var variable in each translation unit, simply define it in each translation unit as

 static int var; 

(although in C ++ this use of static now deprecated and replaced by nameless namespaces).

+12
source

The two #define directives have nothing to do with each other, because they are in different translation units (that is, in the source files). The compiler processes the two source files in complete isolation, so defined(VAR) always false, and the contents of #ifndef always included.

If you want to have one variable shared between several source files, there is an easy way: define it in one source file and declare it in another:

 // other.cpp int var; // Definition. // main.cpp extern int var; // Declaration. 

When linked, they will refer to the same var . Better yet, declare a variable in the header:

 // other.h extern int var; 

Then the files that need var can simply include a header:

 // main.cpp #include "other.h" 

The difference you see between C and C ++ is related to the processing of globally declared identifiers in C compared to C ++. In C, any number of preliminary definitions (without a storage class specifier and without an initializer) can be combined together by the linker into a single character - if all the actual definitions of this character ultimately have the same relationship and storage class. This is done using weak linker characters.

C ++, however, does not have the concept of a test definition and considers an external declaration without a storage class specifier as a definition. Thus, g ++ generates strong linker characters, which leads to conflict during the connection.

0
source

The visibility of global variables in compilation units subtly differs between C and C ++.

If they are for different variables, enclose them in an anonymous namespace in each file.

 namespace { int var; } 

If they are intended for the SAME variable, one of them needs an extern pointer specifier to avoid multiple definitions.

 extern int var; 

Your #define VAR does nothing in the example you posted. The definition is not carried over through compilation modules.

-1
source

Inclusion protections are local to the translation unit. This means that when you execute #define VAR in one .cpp file, it is not defined in any other files.

-1
source

Source: https://habr.com/ru/post/922425/


All Articles