Thread: How to : Using C and C++ headers

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    2

    How to : Using C and C++ headers

    Hi all,

    I'm looking for a document which summarize the equivalence between C and C++ headers. Is there any?

    So far, i've been using this technique when i couldn't find a C++ header equivalent (as far as my knolewdge allows me to do so...) :


    Code:
    extern "C" {
    #include <io.h>
    #include <sys/stat.h>
    }
    Thank you.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    The header itself SHOULD have extern "C" in them, but I guess if they are really low-level headers, maybe no one has updated them. I would post a bug-report to the relevant maintainer (probably glibc).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Nov 2007
    Posts
    2
    Thanks Mat

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    What exactly does putting extern "C" around the #include directives do?

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    It tells the compiler that these function declarations are "C" rather than "C++". This is because certain concepts are every so slightly different in C and C++.

    For example, in C:
    Code:
    int foo();
    means that there is a function foo that returns an integer, and it takes an arbitrary number of arguments.

    In C++ the same would mean "it takes NO arguments".

    Another example is the C++ keyword "new" that is not a keyword in C. So you could have:
    Code:
    extern "C" void foo(int new, int old);
    But without extern "C" the this would cause a compile error.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    This will cause a compile error with extern "C", too. The linkage specification only affects linkage.

    OK, here's the real reason: C names traditionally follow a very simple "name mangling" (that's the process of turning the names you use in the programming language into those used at the final linking level): just prepend an underscore. E.g. this C function:
    Code:
    void foo(void)
    {
    }
    is called _foo at the binary level.

    This C function:
    Code:
    int foo(int i1, int i2, float f, struct bar *pb)
    {
      return i1 * i2 + (int)(f * pb->whoa);
    }
    is also called _foo at the binary level. You can't have both in the same program. Overloading is not allowed in C.

    In C++, a different way had to be found. It uses a much more complicated mangling scheme that encodes the parameter types into the name. E.g. the first foo could become "_foo$v", and the second could become "_foo$iif$$bar$" or something like that. Now the functions can be distinguished.

    The problem is obvious. Compile the first foo with a C compiler. Then use a C++ compiler to compile code that uses it. The C compiler generates the name "_foo", but the C++ compiler will parse the declaration and make a reference to "_foo$v". The linker comes along and can't find "_foo$v" and throws an error.

    The extern "C" tells the C++ compiler to use C mangling rules.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Hmm...
    So does that mean when I write C code, I should always create the headers like this:
    Code:
    #ifdef INCLUDE_GUARD_BLAH_BLAH
    #define INCLUDE_GUARD_BLAH_BLAH
    
    extern "C"
    {
        /* ... */
    }
    #endif
    This ancient C library I'm porting doesn't have that in the headers, but customers are using it in their C++ programs without problems. Is that by luck, or are they putting extern "C" around the headers themselves?

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Actually something like:
    Code:
    #if __cplusplus
    extern "C" {
    #endif
    ...
    #if __cplusplus
    }
    #endif
    Otherwise it won't compile with a non-C++ compiler.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed