Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

wierd visual c++ link error.

2 views
Skip to first unread message

???_blue

unread,
Apr 10, 2000, 3:00:00 AM4/10/00
to
For some reason visual c++ 6 gives me an error stating that a variable
has already been defined in an object. What is going on, the error is:

phat.obj : error LNK2005: "class clEzWin * clCallBack"
(?clCallBack@@3PAVclEzWin@@A) already defined in ezwin.obj

the header file( ezwin.h ) is:

#ifndef __EZWIN_H__
#define __EZWIN_H__

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class clEzWin
{
//class defined

};

void EZ_SetCallBack( clEzWin *clPoint );
LRESULT CALLBACK EZ_MainProc( HWND hMain , UINT uiMsg , WPARAM wpmArg ,
LPARAM lpmArg );

clEzWin *clCallBack;
#endif // __EZWIN_H__


The source file just declares all the functions and includes the header
file. Like this:
#include "ezwin.h"

The "ezwin.h" is included through another file( phat.h ). If anyone know
why the linker is giving me all these errors, I would really appreciate
it, cheers. If you need anymore info, then I will be happy to provide
it, cheers again.

--
???_blue's current PokéDEX stats...
Seen : 93
Owned : 30
S.Note: a Pikachu & Snorlax

Steven Hines

unread,
Apr 10, 2000, 3:00:00 AM4/10/00
to
> The "ezwin.h" is included through another file( phat.h ). If anyone know
> why the linker is giving me all these errors, I would really appreciate
> it, cheers. If you need anymore info, then I will be happy to provide
> it, cheers again.

"ezwin.h" declares:

clEzWin *clCallBack;

so if ezwin.h is #included in any way in more than one source file you
will have a multiple declarations link error.


unorigina...@my-deja.com

unread,
Apr 10, 2000, 3:00:00 AM4/10/00
to
In article <95539301...@cs1.sdd.hp.com>,

Which means that you should replace

clEzWin *clCallBack;

with

extern clEzWin *clCallBack;

in ezwin.h, and then put

clEzWin *clCallBack;

in your ezwin.cpp


Sent via Deja.com http://www.deja.com/
Before you buy.

???_blue

unread,
Apr 11, 2000, 3:00:00 AM4/11/00
to
unorigina...@my-deja.com wrote:

> Which means that you should replace
>
> clEzWin *clCallBack;
>
> with
>
> extern clEzWin *clCallBack;
>
> in ezwin.h, and then put
>
> clEzWin *clCallBack;
>
> in your ezwin.cpp

Now it all makes sense, I now know the point of the extern keyword now,
cheers.

John A. Grant

unread,
Apr 11, 2000, 3:00:00 AM4/11/00
to
"???_blue" <seph...@id-base.com> wrote in message
news:38F2905F...@id-base.com...

> unorigina...@my-deja.com wrote:
>
> > Which means that you should replace
> >
> > clEzWin *clCallBack;
> >
> > with
> >
> > extern clEzWin *clCallBack;
> >
> > in ezwin.h, and then put
> >
> > clEzWin *clCallBack;
> >
> > in your ezwin.cpp
>
> Now it all makes sense, I now know the point of the extern keyword now,
> cheers.

Since you're just getting into this, consider the following
methodology for dealing with 'extern':

myglobals.h
#ifdef __MAIN__
#define GLO(x,v) x v
#else
#define GLO(x,v) extern x
#endif
GLO(int x,);
GLO(float scale,=123.456);
GLO(bool drawbackground,=false);

main.cpp
#define __MAIN__
#include "myglobals.h"

anothermodule.cpp
#include "myglobals.h"

someothermodule.cpp
#include "myglobals.h"

This concentrates your variable definition in a SINGLE
myglobals.h file and makes it easy to modify. When compiled,
only main.cpp will see the variable declaration (and optional
value). All other modules will only see 'extern'.

Otherwise, there's nothing to stop you from doing silly things
like this:
main.cpp
int x;
char title[100];

someothermodule.cpp
extern float x; // wrong
extern char *title; // also wrong

You're just asking for trouble when you spread definitions
and 'extern' across multiple modules.

--
John A. Grant * I speak only for myself * (remove 'z' to reply)
Radiation Geophysics, Geological Survey of Canada, Ottawa
If you followup, please do NOT e-mail me a copy: I will read it here

Xazziri

unread,
Apr 11, 2000, 3:00:00 AM4/11/00
to

John A. Grant <zjag...@znrcanz.gcz.ca> wrote in message
news:8cuf4t$du...@nrn2.NRCan.gc.ca...
Pointless macro magic, in my personal opinion. The 'silly things' can only
happen if modules start externing symbols on their own instead of just
including the .h file. Your solution will not help against that -
unfortunately, you can't MAKE people include the header.

In fact, it only saves you the trouble of modifying multiple files if you
change the type of the variable - changing the name will, ofcourse, still
require you to modify everything else and the initial value is set in the
.cpp. Besides, GLO(int x,) and GLO(float scale,=123.456) are not exactly
elegant or easy to read, are they? I think you'd get more typos with this
approach than linker errors without it. But again, this is just what I
think, as a macrophobic :-)

X.

Rude Dog

unread,
Apr 11, 2000, 3:00:00 AM4/11/00
to
I agree 100% with your comments regarding macros. Unfortunately,
many programmers would much rather try to impress us all with
their nifty little tricks than to write readable, maintainable
code.

* Sent from RemarQ http://www.remarq.com The Internet's Discussion Network *
The fastest and easiest way to search and participate in Usenet - Free!


John A. Grant

unread,
Apr 11, 2000, 3:00:00 AM4/11/00
to
"Rude Dog" <rude-dog...@home.com.invalid> wrote in message
news:108695f7...@usw-ex0102-016.remarq.com...

> I agree 100% with your comments regarding macros. Unfortunately,
> many programmers would much rather try to impress us all with
> their nifty little tricks than to write readable, maintainable
> code.

You and Xazziri are so right. I'm 100% smoke & mirrors and I
don't have a single clue about anything. In fact, I'm a pretty lame
programmer and I rely almost entirely on "macro-magic" to
get anything done. Since my primary goal is to impress and
since I can't do it on the basis of my knowledge and code-writing
abilities, the only way I can impress people is with my use of
macros. In fact, all of the code I write is crap - it's completely
unreadable and completely unmaintainable.

Harold Weissfield

unread,
Apr 11, 2000, 3:00:00 AM4/11/00
to
Now, now, John; everyone has their own styles and preferences, and what's
easier for one person may not be easier for another. I do find it rather
amusing that the name of the person whom you replied to was "Rude Dog"
though; it's somehow all appropiate.

Regards,
Harold Weissfield

"John A. Grant" <zjag...@znrcanz.gcz.ca> wrote in message

news:8d0no9$du...@nrn2.NRCan.gc.ca...

John A. Grant

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
"Harold Weissfield" <h_weis...@hotmail.com> wrote in message
news:8d0ojh$6lo$1...@bob.news.rcn.net...

> Now, now, John; everyone has their own styles and preferences, and what's
> easier for one person may not be easier for another. I do find it rather

(my response is not directed specifically to Harold, but
I will focus on his theme of "styles and preferences" and
"ease of use")

I fully recognize that there are many different styles of coding
and that a style which is appropriate for some people may
not be for others. However, the two comments I received were
absolute comments about the technique, not relative comments,
comparing style or technique X versus Y. Furthermore, they
were not constructive, offering no alternate solutions that were
better or which solved perceived weaknesses in the solution I
presented.

There are legitimate uses of macros and it's one of the strengths
of the C language. Features of any language can be used
appropriately and they can be abused (i.e. "go to" in ANSI
66-era FORTRAN programs). A certain amount of macrophobia
is a good thing, because macros can be used to write unreadable
and unmaintainable code. For C++, inline functions are preferred
to the use of macros.

Also, it's one thing to use macros in static declarations like
this and it's quite another to use macros in place of functions.
How many times have you seen macros like this:
#define XXX(a,b,c,d,e) \
some expression \
and another expression \
and yet another expression \
still more stuff here \
and here \
and here

Then the macro is used like this:
if(XXX(....)) ...

Now *THAT* is unreadable and unmaintainable and represents
a clear abuse of macros and a certain amount of laziness.
Presumably someone could make a case for using macros to
generate in-line code like the above for use in real-time apps
for which function calling overhead is problematic. But it's
absurd to compare my technique for managing global
variables to this macro abuse.

I don't think that the technique I presented is an abuse of the
language and it certainly is not at the expense of readability
or maintainability. The advantage of having a SINGLE file
that contains only a SINGLE instance of the definition AND
initialization of a global variable makes the technique stand
head and shoulders over any other that I have seen.

BTW, I say "my technique", but I take no credit for 'inventing'
it. It's a technique that is used by many people.

One of the strengths of programmers is their ability to adapt
to different ideas. You can take a method or technique
which has some appeal, but which offends your sensibilities
somewhat and modify it and make it your own. For example:

Xazziri, you said:
"...Besides, GLO(int x,) and GLO(float scale,=123.456)


are not exactly elegant or easy to read, are they?"

and yet you didn't provide your (presumably better) solution
to be considered alongside mine. Perhaps you didn't like
the use of 2 variables in the macro. Ok, so adapt the
technique and use this:
#ifdef __MAIN__
#define GLO(x) x
#else
#define GLO(x) extern x
#endif
GLO(int x);
GLO(float y);

Presumably, this does not offend you as much. Given that
this is less offensive and therefore more acceptable to you,
the next step for you is to provide a way of initializing the global
variable. Note that it must be "elegant and easy to read", to
use your own words. However, from your comment:
"...the initial value is set in the .cpp."

I can only conclude that you didn't read or fully understood
the technique I was presenting, did you? Do you really
think that the value is initialized in the .cpp file? On the
contrary, the value is initialized in the .h file, during only
one instance of the #include

Macros are always 'magic'. But are they 'pointless' in this case?
Hardly. I have seen way too many instances of mismatches
that have been created because of a lack of organization (and
understanding) by C programmers. For example:
(a) "int x" versus "extern float x" and "extern int x"
(b) "char title[100]" versus "extern char *title"
(c) "int x=100" versus "int x=200"

Error (c) will be evident at link time, but errors (a) and (b)
are very difficult to find without scouring all of the code.
A simple technique that eliminates this potential error
can be invaluable to everyone.

Why do you think we put all of our function prototypes
in a single 'include' file instead of manually coding
prototypes (or using obsolete K&R syntax) in the
individual .c files? Using a single *.h file ensures a
consistent and uniform definition of the interface to
the function. I don't see any reason to not use the
same technique to provide the same interface to
global variables.

I have also seen way too much code that has hundreds
of 'extern' statements scattered throughout the code - a
nightmare of maintenance, as I'm sure you will agree.

You also said

"silly things' can only happen if modules start externing
symbols on their own instead of just including the .h file.

Unfortunately, you can't MAKE people include the header"

Duh, well you can't actually MAKE people do anything.
This is your own programming project - you can also disable
every warning and error message on your compiler and you
can refuse to use #define STRICT and you can also refuse
to check the return values of API functions. You can refuse
to check for NULL pointers. It's entirely up to you, of course.

The technique I presented, is a technique that I've used for
over 20 years. It's also a technique that is used (in various
forms) by MANY programmers. If you think it's silly, then you
don't have to use it, but if you're going to pronounce it 'pointless',
then you should be prepared to come up with something better.
This is a discussion forum for techniques and we can all learn
something from someone else. I'm quite prepared to learn a
new technique from you or anyone else, but I'm really not
interested in reading unfounded and gratuitous comments
like "pointless macro-magic".

Xazziri

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to

John A. Grant <zjag...@znrcanz.gcz.ca> wrote in message
news:8d10fv$e1...@nrn2.NRCan.gc.ca...

> "Harold Weissfield" <h_weis...@hotmail.com> wrote in message
> news:8d0ojh$6lo$1...@bob.news.rcn.net...
<other sensible comment snipped>

> One of the strengths of programmers is their ability to adapt
> to different ideas. You can take a method or technique
> which has some appeal, but which offends your sensibilities
> somewhat and modify it and make it your own. For example:
>
> Xazziri, you said:
> "...Besides, GLO(int x,) and GLO(float scale,=123.456)
> are not exactly elegant or easy to read, are they?"
>
> and yet you didn't provide your (presumably better) solution
> to be considered alongside mine.
>
First off, I would like to stress the fact that I personally didn't like the
technique you presented. I was not trying to criticize your abilities as a
programmer like 'Rude Dog' suggested (or at least implied).

I was not so presumptuous to claim that I have a better solution. I simply
think the existing language mechanism (extern <variable> in the header, real
declaration in the .cpp) is readable and sufficient.

> Perhaps you didn't like
> the use of 2 variables in the macro. Ok, so adapt the
> technique and use this:
> #ifdef __MAIN__
> #define GLO(x) x
> #else
> #define GLO(x) extern x
> #endif
> GLO(int x);
> GLO(float y);
>
> Presumably, this does not offend you as much. Given that
> this is less offensive and therefore more acceptable to you,
> the next step for you is to provide a way of initializing the global
> variable. Note that it must be "elegant and easy to read", to
> use your own words. However, from your comment:
> "...the initial value is set in the .cpp."
>

See above. Personally, I would use your first version if I used a macro at
all, because this one (and please don't be offended, but I can't resist) is
even more silly. This only aids the programmer who can't get his .cpp to
correspond with his .h properly. Mind you, that's one .cpp and one .h, it
won't have anything to do with any other .cpp's. What I meant was that I
didn't like the syntax of the macro. GLO(int x,) and GLO(float
scale,=123.456) look very strange to me as a run-of-the-mill C++ programmer.
I guess you get used to it.

> I can only conclude that you didn't read or fully understood
> the technique I was presenting, did you? Do you really
> think that the value is initialized in the .cpp file? On the
> contrary, the value is initialized in the .h file, during only
> one instance of the #include
>

No, no, I was talking about the language mechanism again, not your
technique. It got messed up in several edits, and I was careless enough not
to re-read my post properly. Apologies, but this was certainly not what I
meant to say. Oh, I give such good impressions of a moron I sometimes
convince myself. :-)

> Macros are always 'magic'. But are they 'pointless' in this case?
> Hardly. I have seen way too many instances of mismatches
> that have been created because of a lack of organization (and
> understanding) by C programmers. For example:
> (a) "int x" versus "extern float x" and "extern int x"
> (b) "char title[100]" versus "extern char *title"
> (c) "int x=100" versus "int x=200"
>
> Error (c) will be evident at link time, but errors (a) and (b)
> are very difficult to find without scouring all of the code.
> A simple technique that eliminates this potential error
> can be invaluable to everyone.
>

Ah, and this is the key point, I think. Unless two different people work on
the same module (I mean: one person works on the .h, the other on the .cpp),
how can you get your definitions confused? If people include your header,
the definition will be correct. If they don't, well, bad luck, there's
nothing you can do about that. I find it difficult to believe that people
who would get confused using 'extern' would get less confused using macros.

> Why do you think we put all of our function prototypes
> in a single 'include' file instead of manually coding
> prototypes (or using obsolete K&R syntax) in the
> individual .c files? Using a single *.h file ensures a
> consistent and uniform definition of the interface to
> the function. I don't see any reason to not use the
> same technique to provide the same interface to
> global variables.
>

Exactly! Couldn't agree with you more. The header provides the definition,
the .cpp provides the declaration. This goes for prototypes, why not for
global variables? If I paraphrased your technique for functions (and
ofcourse I'm not serious about this), it would be a little like this:

#ifdef __MAIN__
#define GLOFUNC(x,y) x { y }
#else
#define GLOFUNC(x,y) x;
#endif

GLOFUNC(int foo(int bar),
return bar * bar;
)

Wouldn't this ensure that you only need to define a function once, and
update it only in one location? I know the comparison is not quite fair, but
this is the main idea.

> I have also seen way too much code that has hundreds
> of 'extern' statements scattered throughout the code - a
> nightmare of maintenance, as I'm sure you will agree.
>

Absolutely. I've only had the misfortune of deciphering code like that a few
times, but it was enough to make me never want to do it again.

> "silly things' can only happen if modules start externing
> symbols on their own instead of just including the .h file.
> Unfortunately, you can't MAKE people include the header"
>
> Duh, well you can't actually MAKE people do anything.
> This is your own programming project - you can also disable
> every warning and error message on your compiler and you
> can refuse to use #define STRICT and you can also refuse
> to check the return values of API functions. You can refuse
> to check for NULL pointers. It's entirely up to you, of course.
>

Erm... I think we're getting off track here. I meant 'Unfortunately, you
can't MAKE people include the header instead of using 'extern <symbol>' in
their own .cpp.

PS. You managed to disable every error message? Great! Could you share that
trick with me? It would save me a lot of debugging time. :-) Just kidding,
ofcourse!

> The technique I presented, is a technique that I've used for
> over 20 years. It's also a technique that is used (in various
> forms) by MANY programmers. If you think it's silly, then you
> don't have to use it, but if you're going to pronounce it 'pointless',
> then you should be prepared to come up with something better.
>
> This is a discussion forum for techniques and we can all learn
> something from someone else. I'm quite prepared to learn a
> new technique from you or anyone else, but I'm really not
> interested in reading unfounded and gratuitous comments
> like "pointless macro-magic".
>

To make everything completely clear:

- I do not question your programming capabilities.
- I do not question the fact that people use this technique.
- I do not propose a technique of my own, I was merely trying to state the
opinion that the existing language features are sufficient and that the
inconvenience of learning the macro does not justify the benefits.

I hope this clears everything up.

X.


Klaus-Werner Konrad

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
Xazziri <xaz...@gmx.net> schrieb in im Newsbeitrag:
8d1crg$ltm$1...@nereid.worldonline.nl...
>
[snip]

>
> > Why do you think we put all of our function prototypes
> > in a single 'include' file instead of manually coding
> > prototypes (or using obsolete K&R syntax) in the
> > individual .c files? Using a single *.h file ensures a
> > consistent and uniform definition of the interface to
> > the function. I don't see any reason to not use the
> > same technique to provide the same interface to
> > global variables.
> >
> Exactly! Couldn't agree with you more.

I use this technique since the beginning of my
programmer's career, and must agreee too !

> The header provides the definition,
> the .cpp provides the declaration.

NOooooo !

The header file must contain the declaration,
and the .c / .cpp file the definition !


>This goes for prototypes, why not for
> global variables?

And *this* is the real argument; the two
things should treat in the same manner.

--
Klaus-Werner Konrad
(ohne pfiffigen Spruch)


Herman

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
I agree with John Grant. Things should be declared once only, to avoid
typing errors and improve maintainability of the code. The macro method
with some variations thereof, does exactly that and is widely used.

Rude Dog

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
To John Grant:

I am a sh*t-disturber by nature and couldn't resist seeing what
kind of reaction I'd get. From now on I'll refrain from making
those kind of comments. While they may not apply to you
personally, my comments are a result of many years of frustration
on my part, working with the kind of people I described in my
previous post.

Jim M

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
On Tue, 11 Apr 2000 22:41:03 -0400, "John A. Grant"
<zjag...@znrcanz.gcz.ca> wrote:

>"Rude Dog" <rude-dog...@home.com.invalid> wrote in message
>news:108695f7...@usw-ex0102-016.remarq.com...
>> I agree 100% with your comments regarding macros. Unfortunately,
>> many programmers would much rather try to impress us all with
>> their nifty little tricks than to write readable, maintainable
>> code.
>
> You and Xazziri are so right. I'm 100% smoke & mirrors and I
> don't have a single clue about anything. In fact, I'm a pretty lame
> programmer and I rely almost entirely on "macro-magic" to
> get anything done.

<snip>

:-)

Don't tell the boss...

I'm with you on this one.

I used macros recently to get all the function pointers from the open
gl dll, and they came in mighty handy as there are 362 of the little
buggers.

They have their place.

Jimbo
--
@ Derbyshire

Chris Becke

unread,
Apr 13, 2000, 3:00:00 AM4/13/00
to
"John A. Grant" wrote:
> Since you're just getting into this, consider the following
> methodology for dealing with 'extern':

I see some ... words ahve been exchanged over this issue.

> myglobals.h
> #ifdef __MAIN__
> #define GLO(x,v) x v
> #else
> #define GLO(x,v) extern x
> #endif
> GLO(int x,);
> GLO(float scale,=123.456);
> GLO(bool drawbackground,=false);
>
> main.cpp
> #define __MAIN__
> #include "myglobals.h"

Eeep.
Knowing as I do the difference between declarations and definitions I would
tend to avoid this - not because of any misplaced :) macrophobia but because
damnit - once alls said and done you have definitions in the header file.

Given your requirement elsewhere on this thread that those who critisize
your method should produce an alternative though, I go the other way
entirely and say damn it - if you are going to define something in a header
file do it properly! Presented for your inspection is __declspec(selectany).

Guard a difinition of anything with this (Assuming you ahve MSVC 6) and the
linker will happily find and use the first definition it finds and throw
away the rest.

myglobals.h can then, with complete impunity, contain lines such as:

extern __declspec(selectany) int x3=3;

The link errors encountered that originated this thread would never occour.
In addition - the item is defined but once and declared independtly never.

Those amongst us who are macro minded could I suppose turn the line into a
much more compact:

GLO int x3=3;

Simple, compact, hard to screw up, and entirely specific to Microsoft. (The
definition of GLO in this case is left as an excercise to the reader).

Chris
--
VisualC++ & Win32 FAQ: http://www.mvps.org/vcfaq
My Win32 Page: http://www.mvps.org/user32


John A. Grant

unread,
Apr 13, 2000, 3:00:00 AM4/13/00
to
"Xazziri" <xaz...@gmx.net> wrote in message
news:8d1crg$ltm$1...@nereid.worldonline.nl...

>
> John A. Grant <zjag...@znrcanz.gcz.ca> wrote in message
> news:8d10fv$e1...@nrn2.NRCan.gc.ca...

> I was not so presumptuous to claim that I have a better solution. I simply


> think the existing language mechanism (extern <variable> in the header,
real
> declaration in the .cpp) is readable and sufficient.

For you maybe, but lesser, sloppier programmers are
presented endless opportunities to mess it up. There
was a case here where a novice programmer thought
that "char x[100]" and "extern char *" were exactly the same.

Most people can benefit from the reduction of multiple
declarations into a single declaration.

[...]


> Ah, and this is the key point, I think. Unless two different people work
on
> the same module (I mean: one person works on the .h, the other on the
.cpp),
> how can you get your definitions confused? If people include your header,
> the definition will be correct. If they don't, well, bad luck, there's
> nothing you can do about that. I find it difficult to believe that people
> who would get confused using 'extern' would get less confused using
macros.

If a single person was working even on a moderate size
project (perhaps ~200k loc), and using explicit "extern"
in all of the modules, it's very easy to get it screwed up.
For example, you might start off with:
main.cpp
int scale=123;
the remainder of the *.cpp files:
extern int scale;

Then one day, you realize that you need a 'float' scale, so
now you have to make changes in EVERY SINGLE FILE:
main.cpp
float scale=123;
*.cpp
extern float scale;

Not only does that waste a lof of time, if you screw up and
miss just one of those 'extern' statements, you will mess
up the entire project and it will be very difficult to track
down. I'm not talking about 3 source files here - I'm talking
about 500+ source files. Grep can only take you so far.

[...]


> Erm... I think we're getting off track here. I meant 'Unfortunately, you
> can't MAKE people include the header instead of using 'extern <symbol>' in
> their own .cpp.

If I was working on a project with other people and the global.h
was provided for me, I can't imagine why I wouldn't use it. I
would never copy definitions from it. Anyone who is used to
#include would do that. Good C programmers never copy
things from *.h files - just the VB folks.

> - I do not propose a technique of my own, I was merely trying to state the
> opinion that the existing language features are sufficient and that the
> inconvenience of learning the macro does not justify the benefits.

Yes, the features of the language are 'sufficient' to get the
job done. But judicious use of macros can provide a more
robust development environment that will help you get the
job done even better, more reliably and with less code
maintenance requirements. Nobody (?) would question
that STRICT is good for programmers and for the products
they create. I say the same about 'GLO'.

John A. Grant

unread,
Apr 13, 2000, 3:00:00 AM4/13/00
to
"Chris Becke" <chr...@mvps.org> wrote in message
news:38f5096b$0$2...@hades.is.co.za...
> "John A. Grant" wrote:
[...my method...]

> Eeep.
> Knowing as I do the difference between declarations and definitions I
would
> tend to avoid this - not because of any misplaced :) macrophobia but
because
> damnit - once alls said and done you have definitions in the header file.

[...]


> file do it properly! Presented for your inspection is
__declspec(selectany).
>
> Guard a difinition of anything with this (Assuming you ahve MSVC 6) and
the
> linker will happily find and use the first definition it finds and throw
> away the rest.

> myglobals.h can then, with complete impunity, contain lines such as:
>
> extern __declspec(selectany) int x3=3;

But, to use your own words. "once all's said and done, you
have definitions in the header file. It's the same problem
you had with my version. I don't see that it's a problem either
way. My method prevents you from having multiple
initializations. Ok, you could do something stupid like
#define __MAIN__ in more than one module. But the linker
will trap that error. I think I would rather hand a linker
report multiple values, than have the linker "use the first


definition it finds and throw away the rest".

Hmm, a better naming convention is:
#define __XXX__
#include "xxx.h"
so the #define matches the filename.

[...]


> Simple, compact, hard to screw up, and entirely specific to Microsoft.
(The
> definition of GLO in this case is left as an excercise to the reader).

I don't see hardly any difference between the two methods.
1. both methods have the 'extern' and the initialization value
in the same *.h file.
2. both prevent linker errors
3. both are "simple, compact and hard to screw up"

The only difference I can see is that mine is completely
generic and works with any compiler and is 100% ANSI C.
Your method requires a Microsoft compiler.

Xazziri

unread,
Apr 14, 2000, 3:00:00 AM4/14/00
to
John A. Grant <zjag...@znrcanz.gcz.ca> wrote in message
news:8d5jui$du...@nrn2.NRCan.gc.ca...

> "Xazziri" <xaz...@gmx.net> wrote in message
> news:8d1crg$ltm$1...@nereid.worldonline.nl...
> >
<snip>

> > Ah, and this is the key point, I think. Unless two different people work
> on
> > the same module (I mean: one person works on the .h, the other on the
> .cpp),
> > how can you get your definitions confused? If people include your
header,
> > the definition will be correct. If they don't, well, bad luck, there's
> > nothing you can do about that. I find it difficult to believe that
people
> > who would get confused using 'extern' would get less confused using
> macros.
>
> If a single person was working even on a moderate size
> project (perhaps ~200k loc), and using explicit "extern"
> in all of the modules, it's very easy to get it screwed up.
<snip>
Okay, this discussion has gone a little too far already. That's entirely my
fault, ofcourse, as my post, which was intended as a side note, was less
than properly worded. I certainly didn't meant to spark a controversy in a
newsgroup primarily dedicated to helping people with their questions, rather
than trifling over C/C++ programming tastes. So I'll just say this, and then
I'll shut up.

John, the point I was trying to make was that you should have the 'extern
int/float scale' in ONE file, and one file only: main.h, like this:

main.h:
#ifndef MAIN_H
#define MAIN_H
// Function prototypes here
extern float scale;
#endif

main.cpp:
#include "main.h"
float scale = 0.0f;

othermod.cpp:
#include "main.h"
// use scale here

And indeed, people who then choose to go 'extern' on their own instead of
properly including main.h like a good little programmer deserve all the
trouble they can get. The only thing I am trying to say and to which I see
we both agree, really, is this:

Thou shalt not use 'extern' in thy own .cpp files but use the header(s)
supplied by the module's author, lest thou be smitten by the combined wrath
of the compiler, being the judge, and the linker, being the executioner.

And whether you then use macros or not is a matter of personal opinion. I
personally don't like it, but if it works, I say live and let live.

X.

Klaus-Werner Konrad

unread,
Apr 14, 2000, 3:00:00 AM4/14/00
to
John A. Grant <zjag...@znrcanz.gcz.ca> schrieb in im Newsbeitrag:
8d5jui$du...@nrn2.NRCan.gc.ca...
[snip]

> If a single person was working even on a moderate size
> project (perhaps ~200k loc), and using explicit "extern"
> in all of the modules, it's very easy to get it screwed up.
> For example, you might start off with:
> main.cpp
> int scale=123;
> the remainder of the *.cpp files:
> extern int scale;
>
I agree with you, *this* would be really silly !
But - as Xazziri pointed out - the DEFINITION
should be placed in ONE .cpp file, and the
DECLARATION in a .h file.

So you have

globals.h:
extern int scale;

main.cpp:
#include "globals.h"
int scale = 123;

the remainder of the *.cpp files:

#include "globals.h"

BTW: I personally use an own file
for global variables with the name
globals.c / .cpp in my projects.

> Then one day, you realize that you need a 'float' scale, so
> now you have to make changes in EVERY SINGLE FILE:
> main.cpp
> float scale=123;
> *.cpp
> extern float scale;
>

No, see above.
But in any case you have to make changes in every single
file that USES the variable 'scale' in most cases ...

>
[snip]

John A. Grant

unread,
Apr 14, 2000, 3:00:00 AM4/14/00
to
"Xazziri" <xaz...@gmx.net> wrote in message
news:8d6i4r$2na$1...@nereid.worldonline.nl...

> John A. Grant <zjag...@znrcanz.gcz.ca> wrote in message
> news:8d5jui$du...@nrn2.NRCan.gc.ca...
> > "Xazziri" <xaz...@gmx.net> wrote in message
> > news:8d1crg$ltm$1...@nereid.worldonline.nl...
[...]

> Okay, this discussion has gone a little too far already. That's entirely
my
> fault, ofcourse, as my post, which was intended as a side note, was less
> than properly worded. I certainly didn't meant to spark a controversy in a
> newsgroup primarily dedicated to helping people with their questions,
rather
> than trifling over C/C++ programming tastes. So I'll just say this, and
then
> I'll shut up.
On the contrary, I think the discussion is healthy. There's
nothing like an argument to bring out different soutions.
But I'm sure a lot of people tuned out long ago. Their loss :)

> John, the point I was trying to make was that you should have the 'extern
> int/float scale' in ONE file, and one file only: main.h, like this:
>
> main.h:
> #ifndef MAIN_H
> #define MAIN_H
> // Function prototypes here
> extern float scale;
> #endif
>
> main.cpp:
> #include "main.h"
> float scale = 0.0f;
>
> othermod.cpp:
> #include "main.h"
> // use scale here
>
> And indeed, people who then choose to go 'extern' on their own instead of
> properly including main.h like a good little programmer deserve all the
> trouble they can get.

Awww, just when I thought we were on the same wavelength,
you ruined it :) On one hand, we agree on ONE file, but you
only put half of the information in that file - the initialization is
in another file and *that* is the point on which we disagree
(and I think we are going to remain in disagreement0
The whole point of my GLO method is to keep everything in
one file - the data type, the 'extern' and the initialization value.

In your example above, if you decide one day to change
'scale' to a 'double', then you have to make a change in
each of 2 files:
(a) change 'extern float scale' to 'extern double scale'
(b) change 'float scale=0.0f' to 'double scale=0.0'

If you do NOT get both changes, you'll be screwed and
that is exactly the situation that is avoided by using my
GLO method.


>>The only thing I am trying to say and to which I see
> we both agree, really, is this:
> Thou shalt not use 'extern' in thy own .cpp files but use the header(s)
> supplied by the module's author, lest thou be smitten by the combined
wrath
> of the compiler, being the judge, and the linker, being the executioner.

Agreed.

> And whether you then use macros or not is a matter of personal opinion. I
> personally don't like it, but if it works, I say live and let live.

Ok.

John A. Grant

unread,
Apr 14, 2000, 3:00:00 AM4/14/00
to
"Klaus-Werner Konrad" <klaus....@cityweb.de> wrote in message
news:8d6ljv$eqc$2...@news.cityweb.de...

> John A. Grant <zjag...@znrcanz.gcz.ca> schrieb in im Newsbeitrag:
> 8d5jui$du...@nrn2.NRCan.gc.ca...
> [snip]
> > If a single person was working even on a moderate size
> > project (perhaps ~200k loc), and using explicit "extern"
> > in all of the modules, it's very easy to get it screwed up.
> > For example, you might start off with:
> > main.cpp
> > int scale=123;
> > the remainder of the *.cpp files:
> > extern int scale;
> >
> I agree with you, *this* would be really silly !
> But - as Xazziri pointed out - the DEFINITION
> should be placed in ONE .cpp file, and the
> DECLARATION in a .h file.
I disagree - see my latest response to his post, in which
I use his example to demonstrate the problem.

> BTW: I personally use an own file
> for global variables with the name
> globals.c / .cpp in my projects.

Mine is called myapp.glo, partly because I use my GLO
macro, and partly because it's not really a .h and not really
a .cpp - it masquerades as both.

> > Then one day, you realize that you need a 'float' scale, so
> > now you have to make changes in EVERY SINGLE FILE:
> > main.cpp
> > float scale=123;
> > *.cpp
> > extern float scale;
> >
> No, see above.

Ok, not every file then. What I meant was that you have to
make the change in at least 2 places: the file with the 'extern'
and the file that initializes it (see Xazziri's latest example and
my comments).

> But in any case you have to make changes in every single
> file that USES the variable 'scale' in most cases ...

True enough - probably, especially if printing, i.e. "%d"
vs "%g".

0 new messages