scope and linkage rule, very confusing!

P

pembed2003

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.

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?

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?

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:

int h(int i){
again:
if(i == 0)
goto again;
}

does 'again' have function scope? I am confuse. Can someone help me
out?

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!
 
J

Jack Klein

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().
 
I

I. Appel

I think(might be wrong):

file scope: variables declared outside of any functions.
Right.

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?

Maybe I'm wrong, but I suppose that's function scope. Or function body
is treated as a block?
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?

I suppose yes.
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:

int h(int i){
again:
if(i == 0)
goto again;
}

does 'again' have function scope? I am confuse. Can someone help me
out?

Well, can someone help me out too? :)
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?

extern is used for declaring the variable, that's declared in another file
(as far as that variable should be allocated in one and the same place).
That's used to share variables among multiple files of program.
 
V

Vijay Kumar R Zanvar

Jack Klein said:
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);


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.


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.


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().

The structure/enum tags are not covered. Do they have namespace
or scope? What is the difference between these two, then?

Vijay
 
V

Villy Kruse

Well, can someone help me out too? :)

Labels found in an inner block is visible in the entire function. Normal
variables are only visible from the point of definition or declaration to
the end of the current block. Example: (of bad usage of goto).

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

int main(int argc, char *argv[])
{
if (0) {
label:
printf("this is a test\n");
return 0;
}
goto label;
}
 
J

Jack Klein

On Wed, 26 May 2004 12:26:28 +0530, "Vijay Kumar R Zanvar"

[snip]
Every identifier in a C program has four primary characteristics:

1. Scope, covered above.

2. Linkage.

3. Storage duration.

4. Name space.
[snip]

The structure/enum tags are not covered. Do they have namespace
or scope? What is the difference between these two, then?

Vijay

It was less than a year ago that I was able to get broadband at home.
Before then I would have been extremely annoyed at someone who quoted
an entire 200+ line post to add a two-line question at the end. The
message download time for me is no longer an issue, so I will merely
point out that over quoting is still considered bad manners. I think
there are still some newsreaders that will not post a message if the
quoted to new material ratio is too high. You could have snipped as
much from my post as I did.

I thought a little about whether or not to include name space in the
list, as the OP hadn't asked about it and I didn't plan to address it.
On the other hand, if I left it off the list and said there were only
three characteristics, somebody was bound to complain that the C
standard clearly mentions four, and I had forgotten one.

So I did list it, and since you asked...

C defines four types of name space, and no symbol can have two
different definitions in the same scope and in the same name space.
On the other hand, there can be many instances of the same symbol or
identifier in scope if each is in a different name space.

Here they are:

1. Labels (goto labels, that is). They are always easily detectable
by the translator because they only appear correctly in two
circumstances, either followed by a ':' or between the 'goto' keyword
and a semicolon.

2. Struct, union and enum tags. They are easily detected by the fact
that they immediately follow the 'struct', 'union', or 'enum' keyword
in both declaration and instantiation.

3. Each structure and union definition creates its own name space for
the names of its members. They are likewise easily recognized because
they must appear in connection with struct_type_ptr-> or
struct_object.

4. All other identifiers, including those created with typedef.

This allows, for example, either of:

struct name_space /* tag name space */
{
int name_space; /* member name space */
} name_space; /* ordinary name space */

....or:

typedef struct name_space /* tag name space */
{
int name_space; /* member name space */
} name_space; /* ordinary name space */

....but now you can't define an instance of the struct like this:

struct name_space name_space;

....or:

name_space name_space;

....because the typedef name is in the same name space as object names.

Tag and member names are in scope wherever the struct/union/enum
definition is in scope. Like labels, tags and member names have no
linkage.
 

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