struct.h:
#ifndef _STRUCT_H #define _STRUCT_H int i; #endif
#include "struct.h" void main(void) { i = 1; }
"no error if compiled in C compiler." Well, of course there isn't: you can only get Linker errors from the Linker!! See my reply here: http://www.keil.com/forum/docs/thread1812.asp Your file struct.h contains a definition of i; presumably you are also #includeing it in another 'C' source file (struct.c?) so that file will also contain a definition of i - presto! multiple definitions! You need to define i in one file only (eg, main.c) and then just have an extern declaration in your header file. BTW: 'i' is a particularly bad name for a global variable!
I think the two statements don't do any work as they do in C compiler in struct.h:
#ifndef #define
"I think the two statements don't do any work as they do in C compiler" Pardon? I don't understand what you're trying to say! Those lines are a standard 'C' coding practice known as an Include Guard - their purpose is to prevent any problems if you (accidentally) #include the same file twice.
If the only files in your project are main.c and struct.h, then where did struct.obj come from? It certainly looks like two OBJ files are being linked together, and both of them contain a definition for "i". The "ifndef" syntax used here is usually used to protect against the case where a header file is included twice, maybe because another header file references it. It does NOT mean you don't have to use "extern". It is safest to make all variable declarations in ".h" files use extern, and then only actually declare the variable (without extern) inside one (and only one) ".c" file.
There aren't those two lines in any header files in INC directory of KEIL why?
Originally I am puzzled by the OBJ file. Really there are only two files in project,I have no idea where this OBJ file comes from. Thanks to safest suggestion
"If the only files in your project are main.c and struct.h, then where did struct.obj come from?" Maybe he compiled struct.h - if you add a header to a uVision Project, it will get compiled unless you uncheck the 'Include in Target Build' option for the file. "It certainly looks like two OBJ files are being linked together, and both of them contain a definition for 'i'." Yes, if he did compile struct.h he would end up with a struct.obj containing a definition of i! "It is safest to make all variable declarations in '.h' files use extern, and then only actually declare [sic] the variable (without extern) inside one (and only one) '.c' file." This is where we need to take great care to distinguish between definitions and declarations: A declaration simply informs the Compiler about an identifier; it creates no code and allocates no memory; A definition actually provides the code to implement a function, or allocates the storage space for a variable. Therefore, in general, declarations should go in headers and definitions in '.c' files - and multiple definitions in the same scope are not allowed. (BTW: This is all standard 'C' stuff; nothing specifically to do with Keil.)
Dear Mike Hwang, I think you need to brush up on your C before continuing on the embedded development path. Your problems stem from a lack of understanding about the C language. 1. Do *not* put code or define data in an include file. It is extremely bad style and error prone. 2. Always use include guards in your .h files but *don't* use leading underscores like the implementation header files do. Leading underscores followed by an uppercase letter or another underscore are reserved for use by the implementation. 3. If you want to share a global variable with another C module then define in it in one C module and extern it in that C module's .h file. Then, simply include that .h file in the other C modules that require knowledge of the global variable. E.g.
/* Foo.c */ int foo_var; /* Foo.h */ #ifndef FOO_H_INCLUDED #define FOO_H_INCLUDED extern int foo_var; #endif /* FOO_H_INCLUDED */ /* Bar.c */ #include "foo.h" int main(void) { foo_var = 12; return 0; }
uncheck the 'Include in Target Build' option for the file. good suggestion At the end,thanks to everybody.
You can include a header file which declares an identifier in the source file which defines that identifier; eg,
/* Foo.h */ #ifndef FOO_H_INCLUDED #define FOO_H_INCLUDED extern int foo_var; #endif /* FOO_H_INCLUDED */ /* Foo.c */ #include "Foo.h" int foo_var;