468,490 Members | 2,606 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,490 developers. It's quick & easy.

declaration shadows a parameter

Hi all,

When i compile following piece of code,

# include <stdio.h>

void fun(int val)
{
int val; /*problem is here*/
printf("%d\n",val);
}

int main()
{
int num = 1;
fun(num);
return 0;
}

Compiler gives a warning (why not an error?),
In function `fun':
warning: declaration of `val' shadows a parameter

But what i expected is an error something like this,
error: redeclaration of `val'

Can someone explain me the warning ?
Thanks for your time.
Yugi

Don't say to GOD how big your problem is
Say to your problem how big your GOD is

Aug 22 '06 #1
15 51602
main() wrote:
Hi all,

When i compile following piece of code,

# include <stdio.h>

void fun(int val)
{
int val; /*problem is here*/
printf("%d\n",val);
}

int main()
{
int num = 1;
fun(num);
return 0;
}

Compiler gives a warning (why not an error?),
In function `fun':
warning: declaration of `val' shadows a parameter

But what i expected is an error something like this,
error: redeclaration of `val'

Can someone explain me the warning ?
For ease of reference I will call val-A the parameter passed
to the function fun() and val-B the variable declared inside
fun().

What the warning means is that while val-B is in scope ,
every time you use val you will get the value stored inside
val-B not the value passed in val-A. Here's an example:

#include <stdio.h>
int main(void) {
int i=1 ;

printf("%d\n",i) ;
{
int i=2 ;
printf("%d\n",i) ;
}
printf("%d\n",i) ;
return 0 ;
}

The above code will produce output
1
2
1

Shadowing a variable by another variable with the same
name can be useful in certain circumstances although
some would consider it poor style. Consider the following
example.

#define macrofoo(a) { \
int i ; \
/* Code which uses among other things i \
* as an index variable */ \
}

int foo(void) {
int i,a ;
/* More code
......
*/
for (i=1;i<10;i++)
macrofoo(a)
}

In the above example the variable i defined
inside macrofoo takes values independently
from the variable i defined inside foo(). If you
are really passionate about using the name i
for index variables and you want to use macrofoo
in more than one places then you might write
such code. For that reason , when shadowing
occurs you'd want to have a warning rather than
an error which would make the code uncompilable.

Finally , I note that the concept of shadowing appears
in other programming languages.

Spiros Bousbouras

Aug 22 '06 #2
In article <11**********************@b28g2000cwb.googlegroups .com>
main() <dn****@gmail.comwrote:
void fun(int val)
{
int val; /*problem is here*/
[snippage]
Compiler gives a warning (why not an error?) ...
The C standards require only a "diagnostic". A warning, an error,
a beep, flashing the screen, or squirting water out of the floppy
drive (if you still have a floppy drive) can all be a "diagnostic".
(The documentation that comes with the compiler should say something
about its diagnostics.)

See also <http://web.torek.net/torek/c/compiler.html>.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Aug 22 '06 #3
main() wrote:
When i compile following piece of code,
# include <stdio.h>

void fun(int val)
{
int val; /*problem is here*/
printf("%d\n",val);
}
Compiler gives a warning (why not an error?),
gcc errors on this:

b.c:8: error: 'val' redeclared as different kind of symbol

--
Bill Pursell

Aug 22 '06 #4
Chris Torek <no****@torek.netwrites:
In article <11**********************@b28g2000cwb.googlegroups .com>
main() <dn****@gmail.comwrote:
>void fun(int val)
{
int val; /*problem is here*/
[snippage]
>Compiler gives a warning (why not an error?) ...

The C standards require only a "diagnostic". A warning, an error,
a beep, flashing the screen, or squirting water out of the floppy
drive (if you still have a floppy drive) can all be a "diagnostic".
(The documentation that comes with the compiler should say something
about its diagnostics.)
Is even a diagnostic required in this case?

C99 6.2.1p4 says:

If the declarator or type specifier that declares the identifier
appears inside a block or within the list of parameter
declarations in a function definition, the identifier has block
scope, which terminates at the end of the associated block.

I think this means that the scope of the parameter is the outer block
of the function, even though it's declared before the opening '{'.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 22 '06 #5
On Tue, 22 Aug 2006 04:31:27 UTC, "main()" <dn****@gmail.comwrote:
Hi all,

When i compile following piece of code,

# include <stdio.h>

void fun(int val)
{
int val; /*problem is here*/
printf("%d\n",val);
}

int main()
{
int num = 1;
fun(num);
return 0;
}

Compiler gives a warning (why not an error?),
In function `fun':
warning: declaration of `val' shadows a parameter

But what i expected is an error something like this,
error: redeclaration of `val'

Can someone explain me the warning ?
Because it is NOT an error to override the name of a parameter. It may
be a mistake to do so, but the only who knows that it is a mistake is
the one who wrote the code.

As it is legal to override the name the compiler may or may not warn
you here.

Anyway you should initialise each auto variable with 0 or an value
that flags the variable as faulty. That will help you to dedect the
mistake that you have not set it right later on.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
Aug 22 '06 #6
"Herbert Rosenau" <os****@pc-rosenau.dewrites:
On Tue, 22 Aug 2006 04:31:27 UTC, "main()" <dn****@gmail.comwrote:
> When i compile following piece of code,

# include <stdio.h>

void fun(int val)
{
int val; /*problem is here*/
printf("%d\n",val);
}

int main()
{
int num = 1;
fun(num);
return 0;
}

Compiler gives a warning (why not an error?),
In function `fun':
warning: declaration of `val' shadows a parameter

But what i expected is an error something like this,
error: redeclaration of `val'

Can someone explain me the warning ?

Because it is NOT an error to override the name of a parameter. It may
be a mistake to do so, but the only who knows that it is a mistake is
the one who wrote the code.

As it is legal to override the name the compiler may or may not warn
you here.
I don't believe that's correct. Both the parameter and the local
object are at the same block scope, even though the parameter is
declared before the opening '{' of the scope. See C99 6.2.1.

But as far as programmers are concerned, it doesn't matter much
whether it's legal or not; just don't do it, and be glad that the
compiler at least warned you about it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 22 '06 #7
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>Because it is NOT an error to override the name of a parameter. It may
be a mistake to do so, but the only who knows that it is a mistake is
the one who wrote the code.

As it is legal to override the name the compiler may or may not warn
you here.
>I don't believe that's correct. Both the parameter and the local
object are at the same block scope, even though the parameter is
declared before the opening '{' of the scope. See C99 6.2.1.
That seems very surprising. It would have broken existing code to
prohibit it in the standard, and as far as I can remember I have never
used a compiler that treated it as an error (rather than a warning).

-- Richard
Aug 22 '06 #8

main() wrote:
Hi all,

When i compile following piece of code,

# include <stdio.h>

void fun(int val)
{
int val; /*problem is here*/
printf("%d\n",val);
}

int main()
{
int num = 1;
fun(num);
return 0;
}
C has always been a bit fuzzy about parameter declarations. In the
original K&R C, the suggestion was to just mention the parameter names
in the parentheses, then associate the names with types after the
header but before the function block (somewhat like FORTRAN).

The new standard is to mention both the type and name in the header.
Which leaves open the question whether the header has its own lexical
nesting level, or is at the same level as the function body.

If the header is its own level, then it's okay to declare another
variable (or const, or type) inside the function body.

If the header is at the same level as the function body, then it should
be an error to redeclare the same name.

It appears your compiler thinks the header has its own nesting level,
but also warns you if you write this somewhat problematical
declaration.


>
Compiler gives a warning (why not an error?),
In function `fun':
warning: declaration of `val' shadows a parameter

But what i expected is an error something like this,
error: redeclaration of `val'

Can someone explain me the warning ?
Thanks for your time.
Yugi

Don't say to GOD how big your problem is
Say to your problem how big your GOD is
Aug 22 '06 #9
On 22 Aug 2006 19:07:44 GMT, ri*****@cogsci.ed.ac.uk (Richard Tobin)
wrote:
>In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>>Because it is NOT an error to override the name of a parameter. It may
be a mistake to do so, but the only who knows that it is a mistake is
the one who wrote the code.

As it is legal to override the name the compiler may or may not warn
you here.
>>I don't believe that's correct. Both the parameter and the local
object are at the same block scope, even though the parameter is
declared before the opening '{' of the scope. See C99 6.2.1.

That seems very surprising. It would have broken existing code to
prohibit it in the standard,
I find that surprising. I think I've seen that done only twice in
several million lines of code, and both times were errors.
>and as far as I can remember I have never
used a compiler that treated it as an error (rather than a warning).
Bill Pursell posted one yesterday.

--
Al Balmer
Sun City, AZ
Aug 22 '06 #10
Richard Tobin schrieb:
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>>>Because it is NOT an error to override the name of a parameter. It may
be a mistake to do so, but the only who knows that it is a mistake is
the one who wrote the code.

As it is legal to override the name the compiler may or may not warn
you here.
>>I don't believe that's correct. Both the parameter and the local
object are at the same block scope, even though the parameter is
declared before the opening '{' of the scope. See C99 6.2.1.

That seems very surprising. It would have broken existing code to
prohibit it in the standard, and as far as I can remember I have never
used a compiler that treated it as an error (rather than a warning).
Have a look at C90, 6.1.2.1, or C99, 6.2.1.
From the latter (#3 and part of #4):
,---
3 A label name is the only kind of identifier that has function scope.
It can be used (in a goto statement) anywhere in the function in which
it appears, and is declared implicitly by its syntactic appearance
(followed by a : and a statement).
4 Every other identifier has scope determined by the placement of its
declaration (in a declarator or type specifier). If the declarator or
type specifier that declares the identifier appears outside of any block
or list of parameters, the identifier has file scope, which terminates
at the end of the translation unit. If the declarator or type specifier
that declares the identifier appears inside a block or within the list
of parameter declarations in a function definition, the identifier has
block scope, which terminates at the end of the associated block.
`---
i.e. you cannot think of function parameters as
foo()
{
/* Out-of-function: parameters and similar */
int bar;
{
/* start of function body */

}
/* take up the value given by return */
int retval = __return;
}
in "pseudo C" but really have to think of it as
foo()
{
/* Out-of-function */
{
/* parameter list */
int bar;
/* start of function body */

}
/* take up the value given by return */
int retval = __return;
}

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Aug 22 '06 #11
Herbert Rosenau <os****@pc-rosenau.dewrote:
>
Because it is NOT an error to override the name of a parameter.
In the outermost block of the function it is. 6.9.1p9 says that
parameters have block scope, so you have two declarations of the same
identifier with no linkage in the same scope, which violates the
constraint in 6.7p3.

-Larry Jones

These child psychology books we bought were such a waste of money.
-- Calvin's Mom
Aug 22 '06 #12
ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>>Because it is NOT an error to override the name of a parameter. It may
be a mistake to do so, but the only who knows that it is a mistake is
the one who wrote the code.

As it is legal to override the name the compiler may or may not warn
you here.
>>I don't believe that's correct. Both the parameter and the local
object are at the same block scope, even though the parameter is
declared before the opening '{' of the scope. See C99 6.2.1.

That seems very surprising. It would have broken existing code to
prohibit it in the standard, and as far as I can remember I have never
used a compiler that treated it as an error (rather than a warning).
Here's the wording from C99:

6.2.1p4:
If the declarator or type specifier that declares the identifier
appears inside a block or within the list of parameter
declarations in a function definition, the identifier has _block
scope_, which terminates at the end of the associated block.

6.2.1p6:
Two identifiers have the _same scope_ if and only if their scopes
terminate at the same point.

6.7p3 (this is a constraint):
If an identifier has no linkage, there shall be no more than one
declaration of the identifier (in a declarator or type specifier)
with the same scope and in the same name space, except for tags as
specified in 6.7.2.3.

Now consider the code in question:

void fun(int val)
{
int val;
/* ... */
}

The parameter val and the variable val both have block scope. The
"associated block" in both cases is the one defined by the opening and
closing braces. The scope of both "val"s terminates at the same
point, the closing brace. Therefore they're in the "same scope" as
defined in 6.2.1p6, and second declaration of val is a constraint
violation,requiring a diagnostic (which can be either a warning, an
error message, or a smoke signal).

If there's an argument, based on the standard, that the two "val"s
*don't* have the same scope, I'd be interested in seeing it.

I don't believe I've ever seen any existing code that does this
deliberately rather than accidentally. If you really did want to hide
the parameter declaration for some reason, you could always create a
new block:

void fun(int val)
{
{
int val;
/* ... */
}
}

Here the scope of the parameter terminates at the outer '}', and the
scope of the variable terminates at the inner '}'.

Note that this would have been an easy mistake to make in pre-ANSI C,
without prototypes. Someone meaning to write this:

fun(val)
int val;
{
/* ... */
}

could accidentally write this:

fun(val)
{
int val;
/* ... */
}

If the compiler didn't complain, it would be a difficult error to
track down.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 22 '06 #13
In article <4l************@individual.net>,
Michael Mair <Mi**********@invalid.invalidwrote:
>Have a look at C90, 6.1.2.1, or C99, 6.2.1.
From the latter (#3 and part of #4):
>3 A label name is the only kind of identifier that has function scope.
It can be used (in a goto statement) anywhere in the function in which
it appears, and is declared implicitly by its syntactic appearance
(followed by a : and a statement).
Could someone remind me whether the seperate namespace for
labels allows one to use label names that are the same as
library function names (or are reserved for future library
directions) ?

If duplication at that level is allowed, then we might have
a tie-in to the thread that is discussing whether strlen can
be a macro.
--
"It is important to remember that when it comes to law, computers
never make copies, only human beings make copies. Computers are given
commands, not permission. Only people can be given permission."
-- Brad Templeton
Aug 22 '06 #14
[given code of the form:
void f(int var) { int var; /*...*/ }
]
>Chris Torek <no****@torek.netwrites:
>The C standards require only a "diagnostic". ...
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>Is even a diagnostic required in this case?
Yes. Others have quoted the appropriate C-standards sections (the
key is mostly that the two instances of "var" have the same scope
by virtue of having their scopes end at the closing brace). I think
it is worth adding, though, that historic (pre-C89) implementations
(or at least one such) did in fact have some "extra" scopes. In
those compilers (or "that compiler"?), the above was valid and
no diagnostic was required.

(The compiler I am most familiar with, in this case, is the old
VAX PCC. Scopes were numbered: level 0 was "file scope", level 1
was reserved for "function scope" -- goto labels -- and arguments,
and actual block-scope variables inside functions started at level
2. I remember this in particular because I worked on speeding up
the compiler: after a few of us did some other work on hot-spots,
profiling showed symbol table work as a high time-eater. This
turned out to be due to a linear scan of the entire symbol table
at every close brace:

for (all entries in the table) {
if (entry->level current_level)
remove this entry;
}

I put the entries into chains according to their levels, and the
time taken in the "remove entries from symbol table" code dropped
from about 15% to about 0.2%, if I remember right. Initially, I
had a bug in it, because I originally thought the "current level"
only ever went up or down one step at a time, but at the final
close brace for a function, it went from 2 to 0. The breakage was
"interesting".)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Aug 23 '06 #15
Walter Roberson schrieb:
In article <4l************@individual.net>,
Michael Mair <Mi**********@invalid.invalidwrote:
>>Have a look at C90, 6.1.2.1, or C99, 6.2.1.
From the latter (#3 and part of #4):
>>3 A label name is the only kind of identifier that has function scope.
It can be used (in a goto statement) anywhere in the function in which
it appears, and is declared implicitly by its syntactic appearance
(followed by a : and a statement).

Could someone remind me whether the seperate namespace for
labels allows one to use label names that are the same as
library function names (or are reserved for future library
directions) ?
I see nothing prohibiting it -- reservations are mostly for file
scope identifiers.
If duplication at that level is allowed, then we might have
a tie-in to the thread that is discussing whether strlen can
be a macro.
I follow said thread and think that having strlen being a macro
via
#define strlen __builtin_strlen
would have negative repercussions on
#define concat(a,b) a##b
#define JOIN(a,b) concat(a,b)
.....
JOIN(my, strlen)
whereas
#define strlen(s) __builtin_strlen(s)
has problems with
(strlen)(s)

Just consider the preprocessor output -- if your implementation
offers it -- of

#include <stddef.h>
#define concat(a,b) a##b
#define JOIN(a,b) concat(a,b)

#define strlen __builtin_strlen
size_t JOIN(my, strlen)(const char *);
#undef strlen
#define strlen(s) __builtin_strlen(s)

int main (void)
{
(strlen)(s);
return 0;
}
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Aug 23 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Aguilar, James | last post: by
10 posts views Thread by Özden Irmak | last post: by
4 posts views Thread by Brian Lowe | last post: by
7 posts views Thread by Satish | last post: by
6 posts views Thread by Robbie Hatley | last post: by
11 posts views Thread by wuzertheloser | last post: by
reply views Thread by NPC403 | last post: by
reply views Thread by theflame83 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.