Hello everyone, I'm trying to split the C source code of one file into nearly 10 different. It does not work properly due to global variables declared in one header file but used in more than one C files. Compiling of such a project works fine but the linking errors L104 and L118 occur. My question: How can I prevent this errors without creating one header file for every C file? My idea is the following, but it is complicated and additionally unsure if it works:
#ifdef CPVAR extern unsigned char global_var1; extern unsigned int global_var2; extern unsigned long global_var3; #elseif unsigned char global_var1; unsigned int global_var2; unsigned long global_var3; #define CPVAR #endif
Your problem is that this global variables declared in one header file but used in more than one C files is not what you're actually doing. You define the symbols in the header file, instead of just declaring them. If this distinction doesn't mean anything to you, get a proper C textbook and look it up. The trick you're trying to apply won't work, because it only affects a single translation unit. It is quite similar to one that would work. You have to declare the variables in all translation units that use them (by doing it in the header), and define them in exactly one of the source files.
Unfortunately a proper C book ist not available at the moment... Do you mean with extern it is called declaration and without definition? However, does the trick work if it is included in the one and only header file?
#elseif elseif what try #else instead. Erik
Tobias, In short, yes... when you use "extern" that's considered a declaration. While many will decry what you're trying to do with global variables to be heresy, there is a fairly easy way to do it. Make a file called something obvious like GLOBALS.H so that everyone who has to maintain this code will know of your treason. In it, do something like this:
#ifdef DEFINEGLOBALSHERE #define GLOBAL #else #define GLOBAL extern #endif GLOBAL unsigned char global_var1; GLOBAL unsigned int global_var2; GLOBAL unsigned long global_var3;
#define DEFINEGLOBALSHERE
Tobias, I try to desrcibe with in simple examples: this is how you define the variables in every C file: in file1.c
unsigned char global_var1;
unsigned int global_var2;
unsigned long global_var3;
extern unsigned char global_var1; extern unsigned int global_var2; extern unsigned long global_var3;
While many will decry what you're trying to do with global variables to be heresy Of course it is heresy to use a technique that guarantees that the "internal" and external is the same. Making programs that automatically are correct may cost someone a job fixing the bugs your other method has introduced. If a method that makes programming safer> makes it "impure" so friggin what. Is good, maintainable = code not more important than "pure" code. Erik
erik, Your fervor to rebuke me seems to have overpowered your ability to convey your point. Of course it is heresy to use a technique that guarantees that the "internal" and external is the same. Guarantees that the "internal" and external what are the same? Linkage? All I've done is define a kludged linkage specifier. As you well know, none of those variables can or will have both internal and external linkage in the same compilation unit. Making programs that automatically are correct may cost someone a job fixing the bugs your other method has introduced. How does my method affect the "automatic"-ness of anything? If someone misunderstands and tries to put a #define DECLARGLOBALSHERE in another compilation unit, link will fail. If someone doesn't understand and fails to put the definition in ANY unit, link will fail. As such, I'm not sure how this is any less automatic than someone knowing to extern a variable they want to use. If a method that makes programming safer> makes it "impure" so friggin what. Is good, maintainable = code not more important than "pure" code. I'm not sure where the discussion of the relative "purity" of anything came up? Can you elaborate on what you mean?
"Note that this only works with plain vanilla definitions. Initializations won't work. Using the _at_ keyword won't work." It is left as an exercise for the student to devise a scheme that would support initialisers and the _at_ keyword...
sorry, about missing the preview, the highlights in my previous post are all wrong. I was fighting an intruder at the same time. Your fervor to rebuke me seems to have overpowered your ability to convey your point. rebuke???, I agreed with you. I supported your statement "While many will decry what you're trying to do with global variables to be heresy" which, as shown by your post you do not. I'm not sure where the discussion of the relative "purity" of anything came up? Can you elaborate on what you mean? Those that "decry what you're trying to do with global variables to be heresy" are the same that like yo use the expression "not real C" about anything that is legible. Erik
erik, Wow... I guess I totally missed your point. My apologies. Yes, I think when you use that particular method, that things end up being fairly readable, and I personally like it better than having global variables smattered at the top of each C file. Nonetheless, I do find that things I write tend to devolve into ugliness when I'm doing C51 code with this method. For instance, I almost always need to have some variables located with the _at_ keyword, which leads to the following sort of construct:
#ifdef DEFINEGLOBALSHERE #define GLOBAL unsigned char somespecialvar _at_ 0x0200; #else #define GLOBAL extern extern unsigned char somespecialvar; #endif GLOBAL unsigned char somenormalvar;
yes... we can only post so much in the way of preprocessor kung-fu in any one thread. :)
Take a look at the following knowledgebase article for several other ideas about how to do this: http://www.keil.com/support/docs/1868.htm Jon
Problem is solved. Thank you guys!
"Managing software engineers is like trying to herd cats" -Anonymous silicon valley manager
"Managing software engineers is like trying to herd cats" But what if the result is the cat's miauw? Erik