Hi all,
I am reading the book "C How to Program" and in the chapter where it
discuss scope rule, it says there are four scopes for a variable:
function scope
file scope
block scope
function-prototype scope
I think(might be wrong):
file scope: variables declared outside of any functions.
Correct.
block scope: variables declared inside a block such as a function. For
example:
int f(int i, int j){
int k;
return 0;
}
then the variable i, j and k are all block scope, right?
Correct.
function-prototype scope: The book said C ignores those. For example:
int f(int x,int y);
in this case, x and y are function-prototype scope?
Correct. C does ignore these. You can have more than one prototype
for the same function, as long as they all match the type of the
function. Each one can give the parameters different names. And the
actual definition of the function can use different names from any of
the prototypes.
The only use for parameter names in function prototypes is to provide
useful hints to the programmer reading the prototype. Consider the
difference between:
void rectangle(int, int);
....and:
void circle(int height, int width);
function scope: This one I don't know. The book said only labels have
function scope and the 'switch' and 'goto' statements normally uses
those. For example:
This is mixing up two things, and the result is incorrect. There are
two types of labels:
1. Labels that can be the targets of a goto statement, of the form
"some_legal_c_name:". These have function scope. You can "goto" a
label from anywhere in the function that contains the label, even if
the goto statement is before the label definition.
2. Labels that can only appear in a switch statement, namely
"default:" and "case some_integer_constant_expression:". These labels
do not have function scope, they are scoped to the switch block that
contains them. A switch statement can only have one "default:" label,
but there can be more than one switch statement in a function and each
of them can have its own "default:". The same is true for the values
of the expression in the case labels. The value of the expression in
each case label within a single switch must all be different, but more
than one switch in a single function can use the same case values.
int h(int i){
again:
if(i == 0)
goto again;
}
does 'again' have function scope? I am confuse. Can someone help me
out?
Yes, again has function scope. But consider this:
int h(int i)
{
switch (i)
{
case 1: do_something(); break;
case 2: do_something_else(); break;
default: break;
}
switch (i - 1)
{
case 1: do_nothing(); break;
case 2: do_even_less(); break;
default: break;
}
return i;
}
So you can see that each "case 1:", "case 2:", and "default:" label is
scoped to its own switch.
Also, What does static and extern use for? I know static can be used
to make the variable persist after function calls but what about
exter?
Thanks!
Every identifier in a C program has four primary characteristics:
1. Scope, covered above.
2. Linkage.
3. Storage duration.
4. Name space.
The static keyword is overloaded with two different uses related to
both linkage and storage duration.
The three types of linkage are external, internal, and none. Objects
defined inside of any block have no linkage. Objects defined at file
scope (variables and functions) have external linkage by default.
That is, they may be accessed by name from code in other source code
files compiled separately.
If an object or function defined at file scope has the static keyword
added to its definition, its linkage is changed from external to
internal. Its name is not visible to other source files, and they
cannot refer to it by name.
So if you define the following at file scope:
int x;
int func(int param)
{
return x + param;
}
Then "x" and "func" have external linkage. Code in other source files
can read or write "x" and call "func" so long as those other files
have proper declarations of them.
On the other hand, if you have this at file scope:
static int x;
static int func(int param)
{
return x + param;
}
Then "x" and "func" have internal linkage. They cannot be accessed or
called by name from other source files. Other source files can have
an object named "x" and a function named "func", and they will be
different from these.
Going back to the first example, where "x" and "func" have external
linkage because they are defined without "static", they can be used by
name from other source files, but only if those other source files
know about them.
If another source file wants to access "x", it needs a declaration
like this:
extern int x;
This tells the compiler that "x" will exist somewhere else in the
program, so this declaration does not define another "x", just allows
this function the ability to access it when it is defined somewhere
else.
You can also use the "extern" keyword on function prototypes, but it
is not really necessary because function prototypes, like function
definitions, have external linkage by default.
The third category is storage duration, and there are three types,
static, automatic, and allocated.
All objects defined at file scope have static storage duration. They
exist and have an initial value before main() begins execution and
continue to exist until the program ends.
All objects defined at block scope with no storage class keyword, or
with the keywords "auto" or "register" have automatic storage
duration. They come into existence when execution enters their block.
They go out of existence when execution leaves the block. If they are
not specifically initialized when declared, they have indeterminate
values.
But objects defined within a block using the "static" keyword have
static storage duration. Like file scope objects, they exist and have
an initial value before main() starts and last for the entire program.
They keep their current value even when execution leaves their block.
The third storage duration, allocated, applies to memory obtained from
malloc(), calloc(), or realloc(). It persists until it is free'd by
another call to realloc() or free().