Undeclared identifiers after program tidy-up?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • nigelmercier
    New Member
    • Dec 2009
    • 45

    Undeclared identifiers after program tidy-up?

    I've started to split my code into modules, within the same Project folder in my compiler. I've done my best to sort this out, now I need an expert!

    For example, in one of the .C files I have a function clsLCD(). This is defined and declared as a prototype in the associated .C file, plus declared as a prototype in my definitions.h file. However, when I build the project I get Undeclared identiifier 'clsLCD' in expression relating to another .C file that calls the function.

    I've been told to repeat the definitions using extern, but do I have to repeat all the definitions in all the other modules, or can I have a single "defs.c" file with these extern definitions in it?

    Could someone have a look at these files and explain how to get rid of these errors.

    TIA

    Nigel
  • johny10151981
    Top Contributor
    • Jan 2010
    • 1059

    #2
    I have asked a question several days ago about sharing a global variable in different c files.
    including header file.

    This can help you to understand extern

    regards,
    johny

    Comment

    • nigelmercier
      New Member
      • Dec 2009
      • 45

      #3
      Hi Johny,

      I think I understand what extern means, but I'm still confused about how to resolve my problem.

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        You extern declarations should not be in any C/CPP source files. The should be in a H header file. You can then #include that header file into all your C/CPP file thus ensuring all the source files see the same set of declarations.

        Comment

        • nigelmercier
          New Member
          • Dec 2009
          • 45

          #5
          Hi Banfa,

          So if I should change all the declarations in the definitions.h file to extern? I'm pretty sure I tried that, but I'll give it another go.

          Comment

          • johny10151981
            Top Contributor
            • Jan 2010
            • 1059

            #6
            After you define variable in header file as extern then redefine the same variable with the same type without extern in c/c++ file. that will help... If I am not wrong

            johny

            Comment

            • Banfa
              Recognized Expert Expert
              • Feb 2006
              • 9067

              #7
              You are both correct but nigelmercier you appear to have missed the rather important, critical you could say, step of

              "#include that header file into all your C/CPP files"

              Comment

              • nigelmercier
                New Member
                • Dec 2009
                • 45

                #8
                Include the definitions header into all the files? Really?

                [Later] Hey, it worked! I hadn't seen anywhere that I had to do this, thank you.

                [Later still] Hmmm! When I first recompiled there was a single error, saying that the type 'byte' had been redefined, so I figured I could fix that. I now realize that this stopped the linker from running.

                If I comment the typedef out in the main file, I get dozens of 'redefinition' errors saying something has already been defined in the main program - but it hasn't!

                If I comment it out in the definitions.h file I get dozens of 'redefinition' errors, plus loads of other errors, such as '; expected but *** found' and 'Specifier needed'

                [Even later still] If I add extern to all the declarations in the definitions.h file, then I get 'Unresolved extern ***'

                Comment

                • weaknessforcats
                  Recognized Expert Expert
                  • Mar 2007
                  • 9214

                  #9
                  The essential thing to remember is that each .C file is compiled separately.

                  Therefore, all externs and struct declarations must be in that file. Should these externs and struct declarations be required in another .C file as well, then you need to have them there also.

                  In this case you can a) make a copy or b) use a #include file. Making a copy is not a good idea since any changes will need to be made in every.C file that's affected whereas a #include file requires the changes be made in one place only.

                  Comment

                  • nigelmercier
                    New Member
                    • Dec 2009
                    • 45

                    #10
                    The essential thing to remember is that each .C file is compiled separately. Therefore, all externs and struct declarations must be in that file.

                    OK, that makes sense. But why am I still getting a whole bunch of errors?

                    Comment

                    • johny10151981
                      Top Contributor
                      • Jan 2010
                      • 1059

                      #11
                      in that case need to see the error messages

                      Comment

                      • nigelmercier
                        New Member
                        • Dec 2009
                        • 45

                        #12
                        > in that case need to see the error messages

                        Too may to list, see my post above.

                        Comment

                        • Banfa
                          Recognized Expert Expert
                          • Feb 2006
                          • 9067

                          #13
                          Hi Nigel,

                          a number of things could be going wrong.

                          Firstly I misled you slightly you do not want externs in front of everything, in particular you should not have externs in from of typedefs.

                          Secondly if you have more errors than you know what to do with then concentrate on the first one (sometimes the second and third ones provide clarification of the first one so it is worth reading them too). The reason for this is that after you have a single syntax error it is possible for the syntax parser to be unable to properly recover and start producing errors on code lines that would be perfectly valid if only that first error didn't exist. I mean this quite literally, a missing ; from the right (wrong?) place can literally produce hundreds of errors. Once you grow in experience you will learn when it is safe to try and fix the following errors but for now fix the first error an recompile is a not entirely unreasonable approach.

                          [Later still] Hmmm! When I first recompiled there was a single error, saying that the type 'byte' had been redefined, so I figured I could fix that. I now realize that this stopped the linker from running.

                          If I comment the typedef out in the main file, I get dozens of 'redefinition' errors saying something has already been defined in the main program - but it hasn't!
                          OK randomly commenting out lines of code is not a logical approach to programming, understand the error and fix it. Once you commented out a necessary typedef the fact you get lots of apparently in-explicable errors is not worth trying to explain, you are missing the definition of a required type. What you can do is learn from the mistake; observe the errors and remember the pattern for the next time you attempt to use a typedef'd type without actually having typedef'd the type (or included the correct header file).

                          So the actual error is that type 'byte' had been redefined (once you uncomment out the typedef). That is an easy error to explain the compiler has seen the typedef for byte more than once, the second+ time it sees the typedef it is a redefinition from the definition it already has and an error is produced.

                          How can this happen when it only appears once in definitions.h? Again easy to explain, you included the header definitions.h more than once into a single C/CPP file. All the the extern statements are not a problem since in effect all the do is say "hey did you know the symbol XXX exists?" to the compiler. The typedef is a problem because it actually creates something.

                          You have 2 solutions, the first, probably most obvious to a novice, is to make sure that you don't include your headers more than once into any given C/CPP file. However anyone with any experience will tell you that for any project of a reasonable size that allows headers to include other headers it is fairly impossible to ensure this which is why everyone uses the second approach of using include protection. Include protection is something you add to (all) you header files and it looks a little like this
                          Code:
                          #ifndef DEFINITIONS_H_
                          #define DEFINITIONS_H_
                          
                          // Body of header file here
                          
                          #endif
                          It uses the preprocessor (# directives are directives to the preprocessor rather than then compiler) to prevent the contents of the file being included more than once.

                          What happens is that the first time the header is included the symbol (DEFINITIONS_H_ in this case but it can be anything) is not defined so the body of header file is processed including defining the symbol. The second and subsequent times the file is included the symbol is already defined so the #ifndef directive causes the preprocessor to leave out the body of the file. So the file can be included multiple times but its statements will only be included once.

                          Every header file should use a different symbol name (for obvious reasons I hope) and it is convention to base the symbol name on an uppercased version of the actual header file name.

                          Comment

                          • nigelmercier
                            New Member
                            • Dec 2009
                            • 45

                            #14
                            Hi Banfa,

                            Thank you for your detailed reply. First of all, could you clarify what a C/CPP file is. My compiler has .C and .H files, and keeps track of files in a project with a .MCPPI file (plus a bunch of .INI files that get rebuilt on every compile).

                            I only used the comment-out route because I knew there was a multiple typedef definition: one in the main .C file, and one in the .H file.

                            I take your point about a missing ; screwing up dozens of lines, but before I started to split the file it compiled fine.

                            I tried adding extern to the line in the .H file that gave the first error, and it fixed it. So I moved on to the next. After about 4 or 5 ties, I then did the rest. It could have been that the 'Unresolved extern ***' messages could have been there all the time, hiding at the bottom of a long list!

                            Comment

                            • Banfa
                              Recognized Expert Expert
                              • Feb 2006
                              • 9067

                              #15
                              C/CPP file, 2 different types of file, C file if you are developing in C and CPP file if you are developing in C++.

                              Whenever you alter code layout, such as splitting 1 file into many, you run the risk of time spent ironing out introduced errors. The real trick is to avoid this sort of operation by developing in multiple files from the outset.

                              I only saw 1 typedef for byte in the code you posted and none of your files are called main.c

                              This is the first time you have mentioned "unresolved externals". That is a linker error not a compiler error. It is very important to identify which stage of the process is actually producing the errors.

                              Unresolved externals are symbols (functions or variables) that the linker can not resolve when it tries to create the executable. You would be extremely unlikely to get that error developing in a single file because the most likely cause is that you have your code spread across several C files but you are not linking all of the object files produce by compiling the C files.

                              The result is that the linker can not find the functions that are in the missing object file and it reports them functions as unresolved externals.

                              I think at this point it might be worth posting your code again if has change significantly from the original posting and posting the errors you are getting.

                              Comment

                              Working...