Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 521067
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T08:12:41+00:00 2026-05-13T08:12:41+00:00

This might be a dumb question, but maybe someone can provide some insight. I

  • 0

This might be a dumb question, but maybe someone can provide some insight.

I have some global variables defined in a header file (yes yes I know that’s bad, but this is just a hypothetical situation). I include this header file in two source files, which are then compiled into two object files. The global symbols are not referenced anywhere in the code.

If the source files are C, then it looks like the compiler omits the global symbols and everything links without errors. If the source files are C++, the symbols are included in both object files and then I get linker errors. For C++ I am using extern “C” when I include the header.

I am using the Microsoft compiler from VS2005.

Here is my code:

Header file (test.h):

#ifndef __TEST_H
#define __TEST_H

/* declaration in header file */
void *ptr;

#endif

C Source files:

test1.c

#include "test.h"

int main( ) {
    return 0;
}

test2.c

#include "test.h"

C++ Source Files:

test1.cpp

extern "C" {
#include "test.h"
}

int main( ) {
    return 0;
}

test2.cpp

extern "C" {
#include "test.h"
}

For C, the object files look something like this:

Dump of file test1.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 006DC627 ABS    notype       Static       | @comp.id
001 00000001 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   2F, #relocs    0, #linenums    0, checksum        0
004 00000000 SECT2  notype       Static       | .debug$S
    Section length  228, #relocs    7, #linenums    0, checksum        0
006 00000004 UNDEF  notype       External     | _ptr
007 00000000 SECT3  notype       Static       | .text
    Section length    7, #relocs    0, #linenums    0, checksum 96F779C9
009 00000000 SECT3  notype ()    External     | _main
00A 00000000 SECT4  notype       Static       | .debug$T
    Section length   1C, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x0 bytes

And for C++ they look something like this:

Dump of file test1.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 006EC627 ABS    notype       Static       | @comp.id
001 00000001 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   2F, #relocs    0, #linenums    0, checksum        0
004 00000000 SECT2  notype       Static       | .debug$S
    Section length  228, #relocs    7, #linenums    0, checksum        0
006 00000000 SECT3  notype       Static       | .bss
    Section length    4, #relocs    0, #linenums    0, checksum        0
008 00000000 SECT3  notype       External     | _ptr
009 00000000 SECT4  notype       Static       | .text
    Section length    7, #relocs    0, #linenums    0, checksum 96F779C9
00B 00000000 SECT4  notype ()    External     | _main
00C 00000000 SECT5  notype       Static       | .debug$T
    Section length   1C, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x0 bytes

I notice that _ptr is listed as UNDEF when I compile the C source, and it is defined when I compile the C++ source, which results in linker errors.

I understand that this is not a good thing to do in real life, I am just trying to understand why this is different.

Thanks.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-13T08:12:41+00:00Added an answer on May 13, 2026 at 8:12 am

    In C, identifiers have three different types of “linkage”:

    1. external linkage: roughly, this is what people mean by “global variables”. In common terms, it refers to identifiers that are visible “everywhere”.
    2. internal linkage: these are objects that are declared with static keyword.
    3. no linkage: these are objects that are “temporary”, or “automatic”, such as variables declared inside a function (commonly referred as “local variables”).

    For objects with external linkage, you can have only one definition. Since your header file defines such an object and is included in two C files, it is undefined behavior (but see below). The fact that your C compiler doesn’t complain does not mean it is OK to do so in C. For this, you must read the C standard. (Or, assuming no bugs in your compiler, if it is invoked in a standards-compliant mode, and if it complains about something [gives a diagnostic], it probably means your program isn’t compliant.)

    In other words, you can’t test what is allowed by the language by testing something and checking if your compiler allows it. For this, you must read the standard.

    Note that there is a subtle difference between definition and tentative definition.

    $ cat a.c
    int x = 0;
    $ cat b.c
    #include <stdio.h>
    int x = 0;
    int main(void)
    {
        printf("%d\n", x);
        return 0;
    }
    $ gcc -ansi -pedantic -W -Wall -c a.c
    $ gcc -ansi -pedantic -W -Wall -c b.c
    $ gcc -o def a.o b.o
    b.o:(.bss+0x0): multiple definition of `x'
    a.o:(.bss+0x0): first defined here
    collect2: ld returned 1 exit status
    

    Now, let’s change a.c:

    $ cat a.c
    int x; /* Note missing " = 0", so tentative definition */
    

    Now compile it:

    $ gcc -ansi -pedantic -W -Wall -c a.c
    $ gcc -o def a.o b.o
    $ ./def
    0
    

    We can change b.c instead:

    $ cat a.c
    int x = 0;
    $ cat b.c
    #include <stdio.h>
    int x; /* tentative definition */
    int main(void)
    {
        printf("%d\n", x);
        return 0;
    }
    $ gcc -ansi -pedantic -W -Wall -c a.c
    $ gcc -ansi -pedantic -W -Wall -c b.c
    $ gcc -o def a.o b.o
    $ ./def
    0
    

    A “tentative definition” becomes “real definition” in C if there is no other definition. So, we could have changed both files to contain int x;, and it would be legal C.

    So, you may have a tentative definition in the header file. We need to see the actual code to be sure.

    The C standard says that the following is undefined behavior (appendix J.2p1):

    An identifier with external linkage is used, but in the program there does not exist
    exactly one external definition for the identifier, or the identifier is not used and there
    exist multiple external definitions for the identifier.

    C++ may have different rules.

    Edit: As per this thread on comp.lang.c++, C++ does not have tentative definitions. The reason being:

    This avoids having different initialization rules for built-in types and user-defined types.

    (The thread deals with the same question, btw.)

    Now I am almost sure that OP’s code contains what C calls “tentative definition” in the header file, which makes it legal in C and illegal in C++. We will know for sure only when we see the code though.

    More information on “tentative definitions” and why they are needed is in this excellent post on comp.lang.c (by Chris Torek).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

This might sound like a reaaaally dumb question but... why do browsers have a
This might be a dumb question, but I don't get it: I have a
Ok so this might be a dumb question, but I can't seem to figure
this question might look dumb but I need to have a clear idea when
I know this might sound like a dumb question, but I have looked every
This might be a dumb question to some of you and maybe I asked
This might be a dumb question but I have not find the answer when
Ok sorry this might seem like a dumb question but I cannot figure this
This might be a dumb question. But does ADO.net support updating to a database
Ok, this might just be a dumb question, but I was wondering if Bluetooth

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.