Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   variable global and macro #ifdef (http://www.velocityreviews.com/forums/t695892-variable-global-and-macro-ifdef.html)

Mug 08-24-2009 04:52 PM

variable global and macro #ifdef
 
i have quite curious problem on global variable on C++
suppose we have 3 files
-------------test.h----------------
#ifndef TEST_H
#define TEST_H
#include <stdio.h>

int a;
void whatever();

#endif

--------------------test.c --------------------
#include "test.h"

void whatever()
{
a=10;
printf("la la %d \n",a);
}

-----------------main.c-------------
#include "test.h"
int main()
{
a=9;
whatever();
return 0;
}

those files compile perfect with gcc,
with help of macro #ifndef
but with g++,it give me the mutiple defintion error on variable a.
i have to declare "a" as static to make it work.
so i have conclusion that the macro #ifndef dosen't works.
do someone can tell me why #ifndef doesn't work,and is there some
remedy for the problem?
Mug

Juha Nieminen 08-24-2009 05:08 PM

Re: variable global and macro #ifdef
 
Mug wrote:
> -------------test.h----------------
> #ifndef TEST_H
> #define TEST_H
> #include <stdio.h>
>
> int a;
> void whatever();
>
> #endif


> those files compile perfect with gcc,
> with help of macro #ifndef
> but with g++,it give me the mutiple defintion error on variable a.
> i have to declare "a" as static to make it work.


No, you have to make it 'extern' to make it work. You are defining the
same global variable in more than one compilation unit, which causes a
collision at the linking stage.

This has nothing to do with the #ifdef.

Mug 08-24-2009 07:39 PM

Re: variable global and macro #ifdef
 
On Aug 24, 5:08*pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> Mug wrote:
> > -------------test.h----------------
> > #ifndef TEST_H
> > #define TEST_H
> > #include <stdio.h>

>
> > int a;
> > void whatever();

>
> > #endif
> > those files compile perfect with gcc,
> > with help of macro #ifndef
> > but with g++,it give me the mutiple defintion error on variable a.
> > i have to declare "a" as static to make it work.

>
> * No, you have to make it 'extern' to make it work. You are defining the
> same global variable in more than one compilation unit, which causes a
> collision at the linking stage.
>
> * This has nothing to do with the #ifdef.


sure if i declare " a " in main.c and add extern int a in test.h,it
works,
but it was not what i meant, i need to declare the global variable in
a seperated file,NOT in main.
and i am quite persuaded that the problem is from #ifndef, with gcc
the same files compiled and work, because with #ifndef there is just
one compilation unit was include the test.h , that's why there are no
compilation error. (maybe i am wrong, otherwise pls indicate
why with gcc,there were no such problems,and pls give a solution
without the direct decleration in main.c) thanks

Mug 08-24-2009 07:58 PM

Re: variable global and macro #ifdef
 
On Aug 24, 7:39*pm, Mug <exallion.l...@gmail.com> wrote:
> On Aug 24, 5:08*pm, Juha Nieminen <nos...@thanks.invalid> wrote:
>
>
>
> > Mug wrote:
> > > -------------test.h----------------
> > > #ifndef TEST_H
> > > #define TEST_H
> > > #include <stdio.h>

>
> > > int a;
> > > void whatever();

>
> > > #endif
> > > those files compile perfect with gcc,
> > > with help of macro #ifndef
> > > but with g++,it give me the mutiple defintion error on variable a.
> > > i have to declare "a" as static to make it work.

>
> > * No, you have to make it 'extern' to make it work. You are defining the
> > same global variable in more than one compilation unit, which causes a
> > collision at the linking stage.

>
> > * This has nothing to do with the #ifdef.

>
> sure if i declare " a *" in main.c and add extern int a in test.h,it
> works,
> but it was not what i meant, i need to declare the global variable in
> a seperated file,NOT in main.
> and i am quite persuaded that the problem is from #ifndef, with gcc
> the same files compiled and work, because with #ifndef there is just
> one compilation unit was include the test.h , that's why there are no
> compilation error. (maybe i am wrong, otherwise pls indicate
> why with gcc,there were no such problems,and pls give a solution
> without the direct decleration in main.c) thanks


folow my previous post,
with gcc do :
gcc -c test.c
and
gcc -c main.c
it product two object file main.o and test.o
lets see the symbole table with nm command:
zsh/3 3676 % nm test.o
00000004 C a
U printf
00000000 T whatever
and then
zsh/3 3678 % nm main.o
00000004 C a
00000000 T main
U whatever
so we see here the symbole a is note with 00000004 C
it means:
"C" The symbol is common. Common symbols are uninitialized data.
When linking, multiple common symbols may appear with
the same
name. If the symbol is defined anywhere, the common
symbols
are treated as undefined references.
---man nm

with those two object file we can product a executable
with either gcc or g++ without errors

then let's see what happen with g++;
i did g++ -c test.c and g++ -c main.c
then with nm see what happened in symbole table:
surprise:

zsh/3 3681 % nm test.o
00000000 T _Z8whateverv
U __gxx_personality_v0
00000000 B a
U printf
and
zsh/3 3683 % nm main.o
U _Z8whateverv
U __gxx_personality_v0
00000000 B a
00000000 T main

here we see "a" is note with 00000000 B
it means :
"B"
The symbol is in the uninitialized data section (known as BSS ).
--- from man nm

with those two object file,we can NOT have a executable,
i think it may show my point of view,why i think the problem is from
#ifndef
best regard



Joshua Maurice 08-24-2009 07:59 PM

Re: variable global and macro #ifdef
 
On Aug 24, 12:39*pm, Mug <exallion.l...@gmail.com> wrote:
> On Aug 24, 5:08*pm, Juha Nieminen <nos...@thanks.invalid> wrote:
>
>
>
> > Mug wrote:
> > > -------------test.h----------------
> > > #ifndef TEST_H
> > > #define TEST_H
> > > #include <stdio.h>

>
> > > int a;
> > > void whatever();

>
> > > #endif
> > > those files compile perfect with gcc,
> > > with help of macro #ifndef
> > > but with g++,it give me the mutiple defintion error on variable a.
> > > i have to declare "a" as static to make it work.

>
> > * No, you have to make it 'extern' to make it work. You are defining the
> > same global variable in more than one compilation unit, which causes a
> > collision at the linking stage.

>
> > * This has nothing to do with the #ifdef.

>
> sure if i declare " a *" in main.c and add extern int a in test.h,it
> works,
> but it was not what i meant, i need to declare the global variable in
> a seperated file,NOT in main.
> and i am quite persuaded that the problem is from #ifndef, with gcc
> the same files compiled and work, because with #ifndef there is just
> one compilation unit was include the test.h , that's why there are no
> compilation error. (maybe i am wrong, otherwise pls indicate
> why with gcc,there were no such problems,and pls give a solution
> without the direct decleration in main.c) thanks


Just because it happens to work sometimes on some compilers does not
mean it's supposed to work or that it's guaranteed to work by the
standard. The standard clearly requires that each global be defined in
exactly one translation unit. If you put the variable definition "int
a;" in a header and include that header in two different translation
units, you're breaking the One Definition Rule and the results are
undefined, that it, it may work on some compilers and it may not.

Solution: Define the global in exactly one translation unit, be that
main.c or another source file.

Also, it may be working with gcc because ?? gcc assumes a .c file is a
C source file (correct me if I'm wrong), and the C language rules for
what is a definition is different from C++ and its One Definition Rule
is slightly different as well. I \think\ your code is valid C code,
but don't quote me.

Victor Bazarov 08-24-2009 08:01 PM

Re: variable global and macro #ifdef
 
Mug wrote:
> On Aug 24, 5:08 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
>> Mug wrote:
>>> -------------test.h----------------
>>> #ifndef TEST_H
>>> #define TEST_H
>>> #include <stdio.h>
>>> int a;
>>> void whatever();
>>> #endif
>>> those files compile perfect with gcc,
>>> with help of macro #ifndef
>>> but with g++,it give me the mutiple defintion error on variable a.


That's how C++ language works. It's different from the C language.

>>> i have to declare "a" as static to make it work.

>> No, you have to make it 'extern' to make it work. You are defining the
>> same global variable in more than one compilation unit, which causes a
>> collision at the linking stage.
>>
>> This has nothing to do with the #ifdef.

>
> sure if i declare " a " in main.c


What language are you programming in? I strongly recommend sticking to
one language exclusively, unless you have a compelling reason not to (do
you?)

> and add extern int a in test.h,it
> works,
> but it was not what i meant, i need to declare the global variable in
> a seperated file,NOT in main.


You mean, "define", not "declare", the global variable in a separate
file? So do it, what's stopping you?

> and i am quite persuaded that the problem is from #ifndef,


Well, it *isn't*.

> with gcc
> the same files compiled and work, because with #ifndef there is just
> one compilation unit was include the test.h , that's why there are no
> compilation error. (maybe i am wrong, otherwise pls indicate
> why with gcc,there were no such problems,and pls give a solution
> without the direct decleration in main.c) thanks


The difference is in how languages treat declarations of variables
outside of any function. In C the statement

int a;

in the file scope, is not a definition but a "tentative" definition. In
C++ there is no "tentative", it's just a definition. Have the same
statement in more than one translation unit, and C linker will combine
them all to make a single object. The C++ linker, however, will see the
violation of the ODR.

In order to make your code the same in C and C++ (more or less), you
need to (a) declare your object 'extern' in the header:

extern int a; // declaration

and (b) define it in one of the translation units, BUT ONLY IN ONE, like so:

int a(0); // definition

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Pascal J. Bourguignon 08-25-2009 08:26 AM

Re: variable global and macro #ifdef
 
Mug <exallion.long@gmail.com> writes:

> On Aug 24, 5:08*pm, Juha Nieminen <nos...@thanks.invalid> wrote:
>> Mug wrote:
>> > -------------test.h----------------
>> > #ifndef TEST_H
>> > #define TEST_H
>> > #include <stdio.h>

>>
>> > int a;
>> > void whatever();

>>
>> > #endif
>> > those files compile perfect with gcc,
>> > with help of macro #ifndef
>> > but with g++,it give me the mutiple defintion error on variable a.
>> > i have to declare "a" as static to make it work.

>>
>> * No, you have to make it 'extern' to make it work. You are defining the
>> same global variable in more than one compilation unit, which causes a
>> collision at the linking stage.
>>
>> * This has nothing to do with the #ifdef.

>
> sure if i declare " a " in main.c and add extern int a in test.h,it
> works,
> but it was not what i meant, i need to declare the global variable in
> a seperated file, NOT in main.


Then do that! Why aren't you doing what you need to do?



-------------a.h----------------------
#ifndef a_h
#define a_h
extern int a;
#endif
-------------a.c----------------------
#include "a.h"
int a=0;
-------------test.h-------------------
#ifndef TEST_H
#define TEST_H
#include <stdio.h>

void whatever();

#endif
--------------------test.c ------------
#include "test.h"
#include "a.h"

void whatever()
{
a=10;
printf("la la %d \n",a);
}
-----------------main.c----------------
#include "test.h"
#include "a.h"

int main()
{
a=9;
whatever();
return 0;
}
----------------------------------------



> and i am quite persuaded that the problem is from #ifndef,


No, it is not.


--
__Pascal Bourguignon__

James Kanze 08-25-2009 12:09 PM

Re: variable global and macro #ifdef
 
On Aug 24, 6:52 pm, Mug <exallion.l...@gmail.com> wrote:
> i have quite curious problem on global variable on C++ suppose
> we have 3 files
> -------------test.h----------------
> #ifndef TEST_H
> #define TEST_H
> #include <stdio.h>


> int a;
> void whatever();
> #endif


> --------------------test.c --------------------
> #include "test.h"


> void whatever()
> {
> a=10;
> printf("la la %d \n",a);
>
> }


> -----------------main.c-------------
> #include "test.h"
> int main()
> {
> a=9;
> whatever();
> return 0;
>
> }


> those files compile perfect with gcc, with help of macro
> #ifndef but with g++,it give me the mutiple defintion error on
> variable a.


First, when you say "those files compile perfect with gcc", I
presume you mean just test.c and main.c (or did you use some
special option so that gcc would consider test.h as a C source,
and compiler it).

> i have to declare "a" as static to make it work.


Or do it correctly, and declare a extern in the header, and
define it somewhere.

> so i have conclusion that the macro #ifndef dosen't works. do
> someone can tell me why #ifndef doesn't work,and is there some
> remedy for the problem?


It has nothing to do with the #ifdef. You've defined a twice,
once in each translation unit, which is undefined behavior. For
various historical reasons, most C compilers (including gcc)
treat such definitions much as they would a named common in
Fortran, but most C++ compilers (including g++) generate code
such that the linker detects the error. (There is the anomaly
that g++, for some strange reason, compiles even C sources as
C++.)

But whatever---it's undefined behavior in both languages, so you
shouldn't do it. (I've used C compilers in the past where your
example wouldn't work. And it works as C++ with Sun CC today.
Undefined behavior is just that---undefined.)

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

James Kanze 08-25-2009 12:15 PM

Re: variable global and macro #ifdef
 
On Aug 24, 9:39 pm, Mug <exallion.l...@gmail.com> wrote:
> On Aug 24, 5:08 pm, Juha Nieminen <nos...@thanks.invalid> wrote:


> > Mug wrote:
> > > -------------test.h----------------
> > > #ifndef TEST_H
> > > #define TEST_H
> > > #include <stdio.h>


> > > int a;
> > > void whatever();


> > > #endif
> > > those files compile perfect with gcc, with help of macro
> > > #ifndef but with g++,it give me the mutiple defintion
> > > error on variable a. i have to declare "a" as static to
> > > make it work.


> > No, you have to make it 'extern' to make it work.


With g++:-). Without the extern, it's undefined behavior (both
in C and in C++), and some compilers (e.g. Sun CC) do "make it
work" (for some definition of "make it work"---in my book, the
best thing a compiler can do in cases of undefined behavior like
thisis to generate an error).

> > You are defining the same global variable in more than one
> > compilation unit, which causes a collision at the linking
> > stage.


> > This has nothing to do with the #ifdef.


> sure if i declare " a " in main.c and add extern int a in
> test.h,it works, but it was not what i meant, i need to
> declare the global variable in a seperated file,NOT in main.


You need to declare the global variable in every translation
unit in which it is used; this is what the extern is for. You
need to define it in one, and exactly one, translation unit:
whether main.c, test.c or some additional source file, it
doesn't matter.

> and i am quite persuaded that the problem is from #ifndef,


You're wrong.

> with gcc the same files compiled and work, because with
> #ifndef there is just one compilation unit was include the
> test.h, that's why there are no compilation error.


No. The difference is that for historical reasons, gcc treats
global definitions in C differently than in C++. Multiple
global definitions are undefined behavior in both languages, and
different compilers treat them differently.

And the #ifdef doesn't have any effect accross translation
boundaries.

> (maybe i am wrong, otherwise pls indicate why with gcc,there
> were no such problems,and pls give a solution without the
> direct decleration in main.c)


Put the definition in test.c. Or in some separate file that you
also link into the final executable.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

James Kanze 08-25-2009 12:25 PM

Re: variable global and macro #ifdef
 
On Aug 24, 9:59 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote:
> On Aug 24, 12:39 pm, Mug <exallion.l...@gmail.com> wrote:


[...]
> Also, it may be working with gcc because ?? gcc assumes a .c
> file is a C source file (correct me if I'm wrong), and the C
> language rules for what is a definition is different from C++
> and its One Definition Rule is slightly different as well.


It's certainly formulated very differently, but I think that the
net effect is the same---undefined behavior. Historically,
however, many pre-standard C compilers (including the one in the
early versions of Unix) treated uninitialized definitions like a
Fortran named common.

(BTW: his filenames all ended with .c, so presumably, are C
code, and should be compiled as C, and not C++.)

> I \think\ your code is valid C code, but don't quote me.


I don't think so, but it is frequent C code, so most C compilers
don't want to break it.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


All times are GMT. The time now is 01:22 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.