Trying to declare identifier locally and hide a file scope identifier

K

Kobu

The code below isn't compiling for me (error message: conflicting types
for 'total' - pointing to the extern declaration).

Why wouldn't this work, since the types are different, the extern
declaration obviously refers to the 'long total' in total.c? Is my
compiler wrong?



total.c
-------
long total = 30;


main.c
-------

#include <stdio.h>
#include <stdlib.h>

static int total = 20;

int main(void)
{
long temp;
extern long total;

/* rest of main */

temp = total;

printf("%d\n", temp);

system("PAUSE");
return 0;
}
 
K

Kobu

Kobu said:
The code below isn't compiling for me (error message: conflicting types
for 'total' - pointing to the extern declaration).

Why wouldn't this work, since the types are different, the extern
declaration obviously refers to the 'long total' in total.c? Is my
compiler wrong?



total.c
-------
long total = 30;


main.c
-------

#include <stdio.h>
#include <stdlib.h>

static int total = 20;

int main(void)
{
long temp;
extern long total;

/* rest of main */

temp = total;

printf("%d\n", temp);

system("PAUSE");
return 0;
}


I tried the program with main.c changed to the following, and it still
didn't work (same error message):


main.c - 2nd version
------

#include <stdio.h>
#include <stdlib.h>

static int total = 20;

int main(void)
{
int total;
{
long temp;
extern long total;

temp = total;
printf("%d\n", temp);
}
return 0;
}


Shouldn't the 'int total' in main force the 'extern long total' to have
external linkage?
 
C

Christian Kandeler

Kobu said:
The code below isn't compiling for me (error message: conflicting types
for 'total' - pointing to the extern declaration).

You have an identifier with internal linkage at file scope, and then you
"import" another identifier of the same name, which has external linkage
and therefore cannot refer to the same object. As a result, the names
collide.
Why wouldn't this work, since the types are different

Since when does that matter? This is also not allowed:
int a;
double a;
There is no overloading in C.
total.c
-------
long total = 30;


main.c
-------

#include <stdio.h>
#include <stdlib.h>

static int total = 20;

What I'm not completely sure about: Is it legal up to this point? Can you
define an identifier with external linkage in one source file and one of
the same name with internal linkage in another file, as long as you do not
declare the former there also? My Linux system links it without a warning,
but I'm not sure if it's being overly generous.


Christian
 
C

Chris Croughton

What I'm not completely sure about: Is it legal up to this point? Can you
define an identifier with external linkage in one source file and one of
the same name with internal linkage in another file, as long as you do not
declare the former there also? My Linux system links it without a warning,
but I'm not sure if it's being overly generous.

Certainly it's legal, that's the point of having internal linkage, it's
known only to that module. If I had to try to predict every identifier
that some module somewhere in a large system might have defined as an
external name it would be totally unworkable.

(Of course, if C imported the "namespace" concept from C++ it would make
writing libraries much simpler. But don't hold your breath for that...)

Chris C
 
L

Lawrence Kirby

Your compiler is correct.

The standard says in 6.2.2.p4:

"For an identifier declared with the storage-class specifier extern in a
scope in which a prior declaration of that identifier is visible, if
the prior declaration specifies internal or external linkage, the linkage
of the identifier at the later declaration is the same as the linkage
specified at the prior declaration. If no prior declaration is visible,
or if the prior declaration specifies no linkage, then the identifier has
external linkage."

So both declarations of total in main.c have internal linkage, which means
that 'extern long total' is linked to 'static int total = 20' in main.c
and not 'long total = 20' in total.c. However the types are incompatible
for that linking.
I tried the program with main.c changed to the following, and it still
didn't work (same error message):


main.c - 2nd version
------

#include <stdio.h>
#include <stdlib.h>

static int total = 20;

int main(void)
{
int total;
{
long temp;
extern long total;

temp = total;
printf("%d\n", temp);
}
return 0;
}
}
}
Shouldn't the 'int total' in main force the 'extern long total' to have
external linkage?

Yes it should because 'int total' is now the prior declaration that is
visible at 'extern long total', and it has no linkage. However the
standard also says in 6.2.2p7:

"If, within a translation unit, the same identifier appears with both internal and external
linkage, the behavior is undefined."

This situation occurs in your new code. However if I understand you
correctly your compiler produces a misleading diagnostic.

Lawrence
 
K

Kobu

Lawrence said:
Your compiler is correct.

[snipped my incorrect code example]
Yes it should because 'int total' is now the prior declaration that is
visible at 'extern long total', and it has no linkage. However the
standard also says in 6.2.2p7:

"If, within a translation unit, the same identifier appears with both internal and external
linkage, the behavior is undefined."

This situation occurs in your new code. However if I understand you
correctly your compiler produces a misleading diagnostic.

Lawrence


I have a question about internal linkage. I want to define a
file-scope variable with internal linkage (ex: static int i; at top of
translation unit) and then I want this to be shadowed by a different
'i' within a large function. Then inside a nested block in the
function, I want to refer to the file-scope 'i'.

Something like this:

static int i; /* file-scope, internal linkage */

void foo()
{
int i; /* block scope, no linkage */

/* some code here */
{
extern int i; /* block, internal linkage */

/* some code here */
}

/* some code here */
}

/* rest of translation unit */



Your post claims that this is how the C Standard treats deeply nested
'extern' declarations, but my compiler is complaining. Your post:
http://groups-beta.google.com/group..._doneTitle=Back+to+Search&&d#bca14942f7fabe80


My compiler is complaining about internal and external declarations of
same identifier (which tells me the deeply nested 'i' is defaulting to
external linkage, instead of "grabbing" the linkage from the previous
file scope declaration of 'i', like your old post explain -- which is
always what I thought happened).

The standard mentions this "grabbing affect," much like your post did,
but it's defaulting to external. Can someone clear this up (possibly
test this on their compiler, or point out my mistake).
 
E

E. Robert Tisdale

Kobu said:
I have a question about internal linkage. I want to define a
file-scope variable with internal linkage (ex: static int i; at top of
translation unit) and then I want this to be shadowed by a different
'i' within a large function. Then inside a nested block in the
function, I want to refer to the file-scope 'i'.

Something like this:

static int i; /* file-scope, internal linkage */

void foo()
{
int i; /* block scope, no linkage */

/* some code here */
{
extern int i; /* block, internal linkage */

/* some code here */
}

/* some code here */
}

/* rest of translation unit */



Your post claims that this is how the C Standard treats deeply nested
'extern' declarations, but my compiler is complaining. Your post:
http://groups-beta.google.com/group..._doneTitle=Back+to+Search&&d#bca14942f7fabe80


My compiler is complaining about internal and external declarations of
same identifier (which tells me the deeply nested 'i' is defaulting to
external linkage, instead of "grabbing" the linkage from the previous
file scope declaration of 'i', like your old post explain -- which is
always what I thought happened).

The standard mentions this "grabbing affect," much like your post did,
but it's defaulting to external. Can someone clear this up (possibly
test this on their compiler, or point out my mistake).

Your compiler is right and Lawrence's explanation was
a little off in his old post. extern will, as you say,
"grab" the linkage of any visible declaration that
doesn't have no lnkage. The static int i at file scope
is not visible at the point where you declare the nested
extern int i, so the only declaration for i it sees at
that point is the no linkage declaration just inside the
opening brace for void food(). This causes it to default
to external linkage, which creates a conflict with the
internal linkage of the file scope i. Your compiler is
right.
 
K

Kobu

top

Snipped a lot of stuff unrelated to my request below.
This causes it to default
to external linkage, which creates a conflict with the
internal linkage of the file scope i. Your compiler is
right.

I prefer getting an answer from a non-troll.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top