#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    142
    Rep Power
    2

    Multiple definition error


    After reading [url = http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/]geeksforgeeks[/url] and [url = http://en.wikibooks.org/wiki/C_Programming/Variables#extern]wikibooks[/url] I still fail to understand what is causing my error.

    main.c
    Code:
    #include <stdio.h>
    #include "eoc2.h"
    extern int x;
    int main()
    {
        fun();
        printf("%d", x);
    
    }
    eoc2.h
    Code:
    #include <stdio.h>
    #if !defined X_DEF
        #define X_DEF
        x = 3;
    #endif
    
    void fun(void);
    fun.c
    Code:
    #include "eoc2.h"
    extern int x;
    
    void fun(void)
    {
        x = 2;
        return;
    }
    Using what I learned from the geeksforgeeks article, I included the #if condition in the header file. Otherwise, the second time eoc2.h is read, x will be defined the second time.
    I thought this was sufficient prevention, but the IDE still returns a multiple definition error.
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,151
    Rep Power
    2222
    It just looks hosed.

    You try to use x, but x doesn't exist since you never define it. Your two separate externs shouldn't cause a multiple definition. And your header file contains a bare assignment statement outside of any function.

    It's all too hosed up to accurately predict what the compiler and linker will complain about. You already know about neglecting to define a variable and about strewing bare code about, so see what happens when you clean that up.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    142
    Rep Power
    2
    I read your other post on "including extern in the header file, and define the variable in a suitable source file" as well as wikibooks and this article, and ended up with the following code.
    I included my understanding on what each code does; please check if they are correct.

    main.c
    Code:
    #include "extern4.h"
    #include <stdio.h>
    
    int x = 1; // defines and initializes x -> allocates memory
    
    int main()
    {
        printf("inside main\n");
        fun();
        return 0;
    }
    extern4.h
    Code:
    void fun(void);
    
    // declares x
    // does not allocate memory
    // but allows all other functions
    // that include this header file to use x
    extern int x;
    Code:
    #include "extern4.h"
    #include <stdio.h>
    
    void fun(void)
    {
        printf("func: x = %d\n", x); // x can be used because of extern in extern4.h
    }
    I also see that my first header file, eoc2.h was similar to saying
    Code:
    int main()
    {
       x = 3;
    }
    in my pre-header file days.
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,151
    Rep Power
    2222
    And what does your compiler (meaning all the pre-processor, compilation, linking stages) say? That is the final arbiter of what works and what doesn't. FWIW, I don't see any problems with what you have now (outside of the lack of guard defines), but then I don't have the final say in these matters, do I?

    Here is a recommended way to write your header files, say for myfile.h:
    Code:
    #ifndef _MYFILE_H_
    #define _MYFILE_H_
    
    // herein lies the body of myfile.h
    
    #endif _MYFILE_H_
    Now, I have always learned these as "guard defines", though Wikipedia has them under Include guard. The problem is that every time you #include a header file, it gets inserted into the source file being compiled. Since some header files themselves need to #include other header files (eg, a function or array needs a struct declaration which is in another header file) and so you end up #include'ing the same header file(s) more than once, there needs to be some way to avoid the duplicate declaration errors and warnings that that could cause. The solution is to only #include the first inclusion and then to ignore all the rest. The implementation of that solution is that #ifndef conditional compilation statement: the first time it's #include'd, that macro is not defined and so the body of the header file gets #include'd, but every other time after that that macro is defined and the body of the header does not get #include'd. It is a very common and very widely used practice and is one that works and is one that should be learned and applied at all times.

    If this introduces you to the concept of conditional compilation, then I wish to welcome you to it. I am sure that we will end up entertaining many questions from you about it.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,151
    Rep Power
    2222
    Another thing I should talk with you about is the matter of including executable code in header files.

    The basic rule is do not do it! Do not even allow yourself to even begin to consider the question of doing it! It is nothing but trouble and should be avoided at all costs!

    The reality is that it will be allowed in C++, but only under very special circumstances: in-line code, implicit in-line code (by defining a class' methods in the class declaration as well as actual in-line methods for that class), and templates. Realize that those are very special and controlled situations in which the header file is the only logical place to put them. The general rule still applies.

    Now, there are a number of books and tutorials and even teachers (though most of them tend to be in the high schools, passing on their own dirty habits to their unsuspecting students) that advocate this quick-and-dirty method of "multiple file projects" (what you are yourself getting into with Code::Blocks): #include all your different source files into one and compile it. As Eddie the Shipboard Computer said, "This will only end in tears." Its purpose is to work around the fact that every IDE has its own specific way to handle projects; the instructor/author has no control over which IDE the student/reader uses, so instead of having to know how to create projects in every single possible IDE out there, they just simply bypassed all that with their own quick-and-dirty approach. If you only have a simple program with just a few source files, you might just get away with it. But as soon as your program starts to grow in size and complexity, you will suddenly start to get all kinds of "duplicate instance" and "redefinition" errors, none of which you will be able to resolve.

    You're a student now, so a project with two to five source files is huge. When you're working professionally, more than a hundred source files is normal. And no employer will ever allow you to #include executable code, but rather would insist, quite rightly, that you use the conventional project model that you have started to learn.

    Just for fun and speaking of "quick and dirty", what do you know about the history of Microsoft? In the 1970's, when the microcomputer industry was just getting started with business computers running Digital Research's CP/M operating system and home computers (eg, Radio Shack's TRS-80 (AKA "Trash-80"), Texas Instrument's TI-99), most home computers ran BASIC interpreters (not to be confused with Microsoft's Visual Basic from about 20 years ago) that resided in ROM and which often was the home computer's operating system. Microsoft was a computer language company that provided those BASIC interpreters. When IBM decided that it wanted to get into the market with its IBM-PC, they contracted Microsoft to do the language development, but they weren't able to sign on Digital Research for the operating system (there are lots of stories about that). So IBM asked Bill Gates if he could to the operating system and Bill immediately agreed. Then Bill went to visit a competing small software company and bought the owner's student project, an operating system called "QDOS", which he then turned into PC-DOS v1.0. And since IBM's business paradigm was that they sold hardware and just gave the software away as part of the deal, IBM allowed Bill Gates to keep the license on DOS and be allowed to sell his own version of it, MS-DOS, separately. And from that, Bill Gates became a billionaire.

    On YouTube.com, you can watch a PBS special: "Triumph of the Nerds: Accidental Empires" and a TV-movie, "Pirates of Silicon Valley", which dramatizes the birth and growth of both Apple and Microsoft. For example, did you know about Xerox Palo Alto Research Center (Xerox PARC)? How circa 1980 they were running commercials on TV (I remember them) demonstrating the "paperless work place" with computer workstations that had GUI interfaces that use a "mouse" and that they were all wired together on a network and could print out to a laser printer? Steve Jobs walked in and the executives at Xerox, who were completely clueless of the treasures they had developed at PARC, basically just gave all that technology away to Apple. Well, the GUI and the laser printers, but then Jobs made the huge mistake of not also snatching up EtherNet, which is what practically all our networking now is based on.

    I bring this up because of the original QDOS. It stood for "Quick and Dirty Operating System." And now you know the rest of the story.
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    142
    Rep Power
    2
    And what does your compiler (meaning all the pre-processor, compilation, linking stages) say?
    My compiler is telling me nothing is wrong, so I think I'm good. (although still unaccountable for run-time errors)

    I'll also keep in mind about guard defines and not including executables.

    On YouTube.com, you can watch a PBS special: "Triumph of the Nerds: Accidental Empires" and a TV-movie, "Pirates of Silicon Valley", which dramatizes the birth and growth of both Apple and Microsoft.
    You recommended the Triumph of the Nerds on the other thread too; I'll have less time for programming till the beginning of the August, but I'll be sure to watch the two after that.

IMN logo majestic logo threadwatch logo seochat tools logo