Scoping rules

C

Chad

The following question stems from Static vs Dynamic scoping article in
wikipedia.

http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping

Using this sites example, if I go like this:

#include <stdio.h>

int x = 0;
int f () { return x; }
int g () { int x = 1; return f(); }

int main(void) {

printf("%d\n",g());
return 0;
}

I get
$gcc -Wall bi.c -o bi
bi.c: In function `g':
bi.c:5: warning: unused variable `x'
$./bi
0

I'm assuming this means (in this case) that x is static scoped, right?

Chad
 
A

Ancient_Hacker

Chad said:
The following question stems from Static vs Dynamic scoping article in
wikipedia.

http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping

Using this sites example, if I go like this:

#include <stdio.h>

int x = 0;
int f () { return x; }
int g () { int x = 1; return f(); }

int main(void) {

printf("%d\n",g());
return 0;
}

I get
$gcc -Wall bi.c -o bi
bi.c: In function `g':
bi.c:5: warning: unused variable `x'
$./bi
0

I'm assuming this means (in this case) that x is static scoped, right?

Chad


The thing to remember is that in C, the compiler resolves ALL the
scoping at compile time.
That implies static scoping. To do dynamic scoping the compiler would
have to generate code for run-time to see exactly what variables of the
same name were in the current call chain and use those. Even worse
would be dynamic scoping of TYPES, that would be a huge can of
code-generating worms. So C doesnt even think of touching dynamic
scoping.

Generally it's only interpreted languages like SNOBOL, APL, and the
like that can even begin to implement truly dynamic nested scoping.
 
C

Chad

Ancient_Hacker said:
The thing to remember is that in C, the compiler resolves ALL the
scoping at compile time.
That implies static scoping. To do dynamic scoping the compiler would
have to generate code for run-time to see exactly what variables of the
same name were in the current call chain and use those. Even worse
would be dynamic scoping of TYPES, that would be a huge can of
code-generating worms. So C doesnt even think of touching dynamic
scoping.

Generally it's only interpreted languages like SNOBOL, APL, and the
like that can even begin to implement truly dynamic nested scoping.

I see. Going off topic....I've been coming and going from this forum
for the past couple of years. It will never cease to amaze me what I
learn here (good or bad). Between the reading, the late night computer
hacking sessions, and asking questions on these forums, I almost want
to give up my awesome $12.50/hr stocking job and go to school for
computer science.

Chad
 
R

Richard Tobin

Generally it's only interpreted languages like SNOBOL, APL, and the
like that can even begin to implement truly dynamic nested scoping.

Not at all. Many lisps for example provide dynamically scoped variables,
and have the same behaviour when compiled as interpreted.

A simple implementation technique that works for compiled code is
shallow binding, where there is only one location for the variable
"x", and a function that binds x just replaces its value and restores
it when it exits. This does not involve any search to find the
current value.

-- Richard
 
B

Barry Schwarz

The following question stems from Static vs Dynamic scoping article in
wikipedia.

http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping

Using this sites example, if I go like this:

#include <stdio.h>

int x = 0;

This x is a global variable and is visible everywhere within this
translation unit (source file) unless it is temporarily hidden by a
subsequent declaration. Technically, it has file scope, external
linkage, and static duration.
int f () { return x; }
int g () { int x = 1; return f(); }

This x is local to the function g. In g, it hides the global variable
discussed above. It has block scope, internal linkage, and automatic
duration.
int main(void) {

printf("%d\n",g());
return 0;
}

I get
$gcc -Wall bi.c -o bi
bi.c: In function `g':
bi.c:5: warning: unused variable `x'

The variable x that is defined in g is never used.
$./bi
0

I'm assuming this means (in this case) that x is static scoped, right?

There are two completely separate objects named x. One is global; the
other is local to g. The C language does not have anything called
static scope. The scope of each variable x is stated above.


Remove del for email
 
C

Chad

Barry said:
This x is a global variable and is visible everywhere within this
translation unit (source file) unless it is temporarily hidden by a
subsequent declaration. Technically, it has file scope, external
linkage, and static duration.


This x is local to the function g. In g, it hides the global variable
discussed above. It has block scope, internal linkage, and automatic
duration.


The variable x that is defined in g is never used.


There are two completely separate objects named x. One is global; the
other is local to g. The C language does not have anything called
static scope. The scope of each variable x is stated above.

But at the end of the article, they have:
"In other cases, languages which already had dynamic scoping have added
lexical scoping afterwards, such as Perl. C and Pascal have always had
lexical scoping,"

So is lexical scoping different than static scope ?
 
C

CBFalconer

Chad said:
.... snip ...

So is lexical scoping different than static scope ?

C has nothing called static scoping or dynamic scoping. The scope
of an identifier is from the point of declaration to the end of the
block in which declared. In Pascal, the scope is the entire block
in which it is declared.

--
"The mere formulation of a problem is far more often essential
than its solution, which may be merely a matter of mathematical
or experimental skill. To raise new questions, new possibilities,
to regard old problems from a new angle requires creative
imagination and and marks real advances in science."
-- Albert Einstein
 
S

Snis Pilbor

Chad said:
(snip)

I see. Going off topic....I've been coming and going from this forum
for the past couple of years. It will never cease to amaze me what I
learn here (good or bad). Between the reading, the late night computer
hacking sessions, and asking questions on these forums, I almost want
to give up my awesome $12.50/hr stocking job and go to school for
computer science.

In my experience, comp.lang.c is leagues better than the typical
computer science dept. It's sort of tragic, but except possibly at
rare/ivy league schools, computer science departments have one purpose
these days: to mass produce javamonkies to do business software.
While comp.lang.c discusses subtle, beautiful issues which often make
me literally grin with amusement, a typical university undergraduate
comp sci class will drive any rational man to suicidal depression. The
theory courses are a bit better, but there they still go too slow. A
4th year course on computability theory should NOT spend a lecture
reviewing basic induction!

No, my friend, what you could do is give up your awesome $12.50/hr
stocking job and go to school for mathematics with an emphasis in
theoretical computer science. Study higher logic, algorithms,
computability theory, language theory, graph theory, coding theory,
combinatorics, artificial intelligence, quantum computers, DNA
computers, etc. in class-- study specific languages on your own/on
usenet. Afterall, do you really need a whole bloody semester to learn
"Java = syntax of C except 80% of the features are crippled and it runs
slower than an abacus"?
 
R

Richard Tobin

So is lexical scoping different than static scope ?
[/QUOTE]

They're often used interchangably.
C has nothing called static scoping or dynamic scoping.

C is statically scoped. Whether the standard mentions this in those
terms doesn't change the fact of the matter.
The scope
of an identifier is from the point of declaration to the end of the
block in which declared.

This is an example of static scoping.
In Pascal, the scope is the entire block
in which it is declared.

This is another example of static scoping.

-- Richard
 
A

Ancient_Hacker

CBFalconer said:
... snip ...
In Pascal, the scope is the entire block
in which it is declared.


... except in Pascal you can plonk a procedure into another procedure
block, and the inner perocedure is free to declare the same name,
overriding the enclosing block. Which is a great comfort, and
somertimes a nuisance.

.... and there's the very handy and sometimes dangerous "with" statement
which opens up any scope you want, including structs, units, and
objects.
 
K

Keith Thompson

Ancient_Hacker said:
In Pascal, the scope is the entire block

.. except in Pascal you can plonk a procedure into another procedure
block, and the inner perocedure is free to declare the same name,
overriding the enclosing block. Which is a great comfort, and
somertimes a nuisance.
[...]

C has almost exactly the same feature, except that you can only nest
blocks, not procedures (functions).
 
R

Richard Tobin

.. except in Pascal you can plonk a procedure into another procedure
block, and the inner perocedure is free to declare the same name,
overriding the enclosing block. Which is a great comfort, and
somertimes a nuisance.
[/QUOTE]
C has almost exactly the same feature, except that you can only nest
blocks, not procedures (functions).

The function version is much harder to implement, because you can call
the inner function recursively. In a recursive call to the inner
function you need to be able to access both the inner function's own
variables, and the outer function's, and these will be in different
stack frames. Typically this is implemented by having the inner
function's stack frame point to the outer one's; this structure is
known as a display. Of course there may be multiple levels of nested
procedure each called recursively, and inner functions may call outer
functions.

Nested blocks on the other hand can just share the containing
function's stack frame.

-- Richard
 
K

Keith Thompson

C has almost exactly the same feature, except that you can only nest
blocks, not procedures (functions).

The function version is much harder to implement, because you can call
the inner function recursively. In a recursive call to the inner
function you need to be able to access both the inner function's own
variables, and the outer function's, and these will be in different
stack frames. Typically this is implemented by having the inner
function's stack frame point to the outer one's; this structure is
known as a display. Of course there may be multiple levels of nested
procedure each called recursively, and inner functions may call outer
functions.

Nested blocks on the other hand can just share the containing
function's stack frame.[/QUOTE]

Yes, but I think name solution is about the same in both cases.
 
C

Chad

Okay, so I started think more about this while at work. Here is where
I pinpointed where I might be confused. Given the following:

#include <stdio.h>

int x = 1000;

int main(void) {

int x = 5;

printf("%d\n",x);
return 0;
}

$gcc -Wall -Wshadow bi.c -o bi
bi.c: In function `main':
bi.c:9: warning: declaration of `x' shadows a global declaration
bi.c:3: warning: shadowed declaration is here
$./bi
5

I guess I don't see the danger with this.
 
S

Snis Pilbor

Chad said:
Okay, so I started think more about this while at work. Here is where
I pinpointed where I might be confused. Given the following:

#include <stdio.h>

int x = 1000;

int main(void) {

int x = 5;

printf("%d\n",x);
return 0;
}

$gcc -Wall -Wshadow bi.c -o bi
bi.c: In function `main':
bi.c:9: warning: declaration of `x' shadows a global declaration
bi.c:3: warning: shadowed declaration is here
$./bi
5

I guess I don't see the danger with this.

It's exactly what it says it is, a warning - in a giant software
project spanning dozens of .c and .h files, I do not want every single
thing to silently, untraceably break the instant someone forgets some
name is already used as a global variable and reuses it in some
function. The drawback is a whiny compiler when you do the above,
which honestly is quite lousy coding style and utterly pointless
anyway. All things considered, the tradeoff is good. Why do you want
dynamic scoping so badly anyway? I can see where it would be useful in
interpreted languages where you can literally create new functions in
realtime as strings, like TCL, but in C it seems the only conceivable
use would be to make it easier to do copy & paste hackjobs, and that's
a bad idea to start with. "A rose by any other name..."

Snis P.
 
C

Chad

Snis said:
It's exactly what it says it is, a warning - in a giant software
project spanning dozens of .c and .h files, I do not want every single
thing to silently, untraceably break the instant someone forgets some
name is already used as a global variable and reuses it in some
function. The drawback is a whiny compiler when you do the above,
which honestly is quite lousy coding style and utterly pointless
anyway. All things considered, the tradeoff is good. Why do you want
dynamic scoping so badly anyway? I can see where it would be useful in
interpreted languages where you can literally create new functions in
realtime as strings, like TCL, but in C it seems the only conceivable
use would be to make it easier to do copy & paste hackjobs, and that's
a bad idea to start with. "A rose by any other name..."

Snis P.

I don't want dynamic scoping. I really don't.
 
C

CBFalconer

Chad said:
Okay, so I started think more about this while at work. Here is
where I pinpointed where I might be confused. Given the following:

#include <stdio.h>

int x = 1000;

int main(void) {
int x = 5;

printf("%d\n",x);
return 0;
}

$gcc -Wall -Wshadow bi.c -o bi
bi.c: In function `main':
bi.c:9: warning: declaration of `x' shadows a global declaration
bi.c:3: warning: shadowed declaration is here
$./bi
5

I guess I don't see the danger with this.

There is none. It is simply warning you that you have made that
file scope x unavailable within the function main. This might not
be what you desire. OTOH it is sometimes used to deliberately hide
the outer declaration.

--
Some informative links:
< <http://www.geocities.com/nnqweb/>
<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/>
 
R

Richard Tobin

$gcc -Wall -Wshadow bi.c -o bi
bi.c: In function `main':
bi.c:9: warning: declaration of `x' shadows a global declaration
bi.c:3: warning: shadowed declaration is here
$./bi
5
I guess I don't see the danger with this.
[/QUOTE]
There is none. It is simply warning you that you have made that
file scope x unavailable within the function main. This might not
be what you desire.

For example, you might add a local variable "x" to a function without
noticing that it already uses the global variable "x". Gcc's warning
helps you avoid that.

-- Richard
 

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

Forum statistics

Threads
474,266
Messages
2,571,075
Members
48,772
Latest member
Backspace Studios

Latest Threads

Top