This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello Forum,
this is a repost from an other forum into which i posted by error.
Recently I came across a strange behaviour to that I want a comment please.
Environment: CCS4 under WinXP for C2000
I have a main.c with some global variables defined there like:
Uint16 Variable1;
enum { ..., A, B, ... } Variable2;
Both variables are reused in a file subroutines.c.
I did there the follwing mistake:
extern Uint32 Variable1; (- instead of Uint16)
extern enum { ..., B, A, ...} Variable2; (- instead of A,B)
CCS4 silently compiled several times ignoring the mismatches until I found the difference using the debugger.
I retested that again and the compiler still does not show any errors or warnings.
Is this intentionally or are there any compilerflags to find such inconsistencies?
rgds
FJ
The compiler is not required to report on inconsistent declarations between C files. To catch such inconsistencies, you should place the external declarations in a header file, and #include it in each source file. Then the compiler will check that the definition in the C file matches the declaration in the header file and report any errors. This FAQ page has good reference material on this subject.
Hello Aarti,
thank you for the reply and the link to the FAQ.
I will review these FAQs in order to improve the structure of the code further.
I will try to verify the proposal tomorrow and if solved consider the question closed.
Kind regards and many thanks.
FJ
FJ,
With regard to the enumeration variable, the association between the extern declaration and the actual object is done at link time and at best the fact that it is a enumerated type is probably the most that is carried with the object name. Even this amount of information is unlikely included with the link information. Because of this lack of information, this is most likely the same problem with the change in size for variable1. The linker doesn't really care much about the layout of the identifiers, its job is to provide addressing which fills in the externed references.
Usually when variables are shared between objects, the header file contains the externed statements. Then you should include the header in both files. This way, the compiler will detect the incorrectness and issue a warning. By the time you get to linking, it is assumed the compiler has doen all the necessary checking of the code. Using the header file system properly will save you many headaches with these types of errors.
Jim
Hello forum,
The problem still stays.
Today I rearranged the code in that way:
file global_variables.c for all the definitions (according to the mentioned FAQ):
Uint16 Variable1;
enum { ... ,A,B, ... } Variable2;
file global_varaibles.h with all the declarations:
extern Uint16 Variable1;
extern enum { ... ,A,B, ... } Variable2;
I include the global_variables.h in all .c source files - except global_variables.c (results in a lot of redefinition errors if done there).
Nevertheless the compiler still does not find the problem if I change the declaration in the .h file to something else as defined in the .c file (e.g. Uint32 Variable1 in .h).
I thought to do everything correct now?
With kind regards
FJ
Friedrich Janus said:I include the global_variables.h in all .c source files - except global_variables.c (results in a lot of redefinition errors if done there).
The header file needs to be included in global_variables.c as well for it to identify type mismatches between the definition and declaration. You should make sure that variables and functions are not "defined" in both C and header files.
The following files will generate the mismatch error:
global_variables.h
---------------------
extern unsigned long Variable1;
enum myenum {A,B};
extern enum myenum Variable2;
global_variables.c
---------------------
#include <global_vars.h>
unsigned int Variable1;
enum myenum Variable2;
FJ,
Ok, so now we are running into some semantics of the language itself. So here is the short answer, you need to use tags for your aggregate types so you can declare variables with them rather than redefining them which is illegal. Example...
This is the proper method for declaring any aggregate type (aggregate meaning struct, union, or enum). The reason for doing it this way is to allow the header file to be included by the globals.c file without generating the errors. This is described in section 6.7.2 of the C99 standard. Specifically, the statement of
Thus, when you included your header file in the globals.c file, the re-definition of the enumerated type was illegal syntax. The difference between a definition and a declaration is subtle for many people and especially for those learning the language.
In your definition of the enumerated type there was no tag so the type was an unnamed enumeration for which the compiler gives a unique tag name to which we never get to see. Then when it was defined again, the next unique tag name was different so now the declarations from the header file and that in the .c file were different because they referenced different (internal) tag names.
You might be wondering why the two declarations of the Uint16 looks the same except for the extern specifier. This is legal because neither instance defines what a Uint16 is but both merely declare it. The Uint16 is defined elsewhere in another header file somewhere.
Hope this helps,
Jim
Hello Jim, hello Aarti,
thank you for the detailed description and the help provided.
I understood the item, rearranged the code again and now everything works now fine.
Even defining additional structures worked so I think I have grasped the difference now.
One more request if that is possible:
The discussed item (global variables) is - to my opinion - not related to the direct basic understanding of the language rather than coding style.
Can you point me to a good reading (book, WWW, TI papers?) that covers this items (how to produce readable code, how to separate, conventions, rules, ..)?
Greetings
FJ
Friedrich Janus said:Can you point me to a good reading (book, WWW, TI papers?) that covers this items (how to produce readable code, how to separate, conventions, rules, ..)?
This is not the best forum for such a question. I recommend you try some of the general C programming forums on the web. One online resource I find useful for general C questions is http://c-faq.com/ .
Thanks and regards,
-George
FJ,
The defacto standard reading is a book entitled "The C programming language" written by Brian Kernighan & Dennis Ritchie. You can get it at just about any book store. These are the guys that invented the language and they also do a pretty good job of describing its use in general in this book. If you really want the gory details, you can download the latest ISO/IEC 9899 standard defining the C programming language here
http://focus.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=slau132e&fileType=pdf
Although the standard is THE reference for the language, it is rather dull reading and very detail oriented, but since it is free, you may want to have a copy anyway.