scope of function parameters

E

Esash

I was asked in an interview :
What is the scope of the parameters that are passed to a function inside the function?
For ex : int add (int a, int b)
{
return (a+b);
}

here, what is the scope of a & b inside the functions ?

I got confused with passing by value and passing by reference. Can anyone please clarify ?
 
N

Noob

Esash said:
What is the scope of the parameters that are passed to a function
inside the function? I got confused with passing by value and passing
by reference. Can anyone please clarify?

There is no such thing as "pass by reference" in C. It's a C++ concept.

Function parameters have block scope.
3.1.2.1 Scopes of identifiers

An identifier is visible (i.e., can be used) only within a region
of program text called its scope. There are four kinds of scopes:
function, file, block, and function prototype. (A function prototype
is a declaration of a function that declares the types of its
parameters.)

[...]

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 } that closes
the associated block. If the declarator or type specifier that
declares the identifier appears within the list of parameter
declarations in a function prototype (not part of a function
definition), the identifier has function prototype scope ,which
terminates at the end of the function declarator. If an outer
declaration of a lexically identical identifier exists in the same
name space, it is hidden until the current scope terminates, after
which it again becomes visible.
 
I

Ian Collins

Esash said:
I was asked in an interview :
What is the scope of the parameters that are passed to a function inside the function?
For ex : int add (int a, int b)
{
return (a+b);
}

here, what is the scope of a & b inside the functions ?

Section 6.9.1p9 in the C(( standard sums it up:

Each parameter has automatic storage duration. Its identifier is an
lvalue, which is in effect declared at the head of the compound
statement that constitutes the function body (and therefore cannot be
redeclared in the function body except in an enclosed block).
I got confused with passing by value and passing by reference. Can anyone please clarify ?

Were you looking for a C++ job?
 
J

James Kuyper

I was asked in an interview :
What is the scope of the parameters that are passed to a function inside the function?
For ex : int add (int a, int b)
{
return (a+b);
}

here, what is the scope of a & b inside the functions ?

Like most identifiers, the scope of a function parameter "begins just
after the completion of its declarator". In this case, the scope of 'a'
begins with the comma that follows 'a', and the scope of 'b' begins with
the ')' that terminates the parameter list. The only identifiers which
don't work this way are structure, union, and enumeration tags.
(6.2.1p7) This means that you can do things like:

void example(int n, char array[][n][sizeof n])
{
....

Function parameters have block scope, which means that their scope ends
at the '}' which terminates the outermost block of the function.
I got confused with passing by value and passing by reference. Can anyone please clarify ?

In C, parameters are passed strictly by value. Things that other
languages, such as Fortran, implement using pass by reference are
implemented in C by creating a pointer value that refers to the thing
you want to pass, and instead passing that pointer, by value.

Functionally, dereferencing a pointer passed by value enables the same
things that passing the pointed-at object by reference would have
allowed: the function can change the value of that object, and it can
view changes to the value of that object which occur during the
execution of the function.
 
C

Chad

Is block scope the same as lexical scope? If not, then what's the difference.


Chad
 
L

Les Cargill

Chad said:
Is block scope the same as lexical scope? If not, then what's the difference.


Chad

Lexical scope is mostly about compilation units. Block scope is about
pairs of curly braces - "blocks".

If there's an "extern" of it, it's no longer lexical scope. It's
public/global. If it's a non-block-scope "static", then it's
lexical scope.

Your mileage may vary.
 
E

Eric Sosman

Lexical scope is mostly about compilation units. Block scope is about
pairs of curly braces - "blocks".

If there's an "extern" of it, it's no longer lexical scope. It's
public/global.

`extern' and `static' do not affect the scope of an
identifier; they affect its linkage, which is a different
matter. Demonstration:

int f(void) {
extern int global(void);
return global();
}

int g(void) {
return 2 * global(); // Undefined behavior
}

Pre-ANSI compilers differed on this, but the original
ANSI Standard decided to keep the notions of "scope" and
"linkage" separate. As a compromise and a nod to existing
implementations that did things the other way (says the
Rationale), the committee chose not to require the compiler
to diagnose the problem, but left the behavior undefined.
If it's a non-block-scope "static", then it's
lexical scope.

Perhaps, depending on what you mean by "lexical scope" (a
phrase the Standard does not use). What the Standard *does*
say is that a `static' declaration outside any block has
"file" scope (6.2.1p4) and "internal" linkage (6.2.2p3).
Your mileage may vary.

As the Rationale says, "This has traditionally been a
major area of confusion."
 
B

Ben Bacarisse

Chad said:
Is block scope the same as lexical scope? If not, then what's the
difference.

They are terms at different levels of explanation. The C standard
defines block scope as one kind of scope an identifier can have (the
others being file scope, function scope, and function parameter scope).
All of C's scope rules combine to make C a "lexically scoped" language.

Almost all programming languages use lexical scope. To a first
approximation, it means that the object (or sometimes the value) to
which a name is bound is determined by the static structure of the
program text (essentially the nesting of functions, blocks and so on).

Some older languages (Lisp and SNOBOL spring to mind) did things
differently, though even there, when Lisp was standardised, static
scoping was made the default.
 
G

glen herrmannsfeldt

(snip)
In C, parameters are passed strictly by value. Things that other
languages, such as Fortran, implement using pass by reference are
implemented in C by creating a pointer value that refers to the thing
you want to pass, and instead passing that pointer, by value.

By the way, Fortran doesn't necessarily use pass by reference.
It can also use pass by value result, otherwise known as copy-in
copy-out.

I have known Fortran compilers that passed all scalars by
value result, as it is sometimes more efficient to access
them that way.

For current compilers, it is done when a non-contiguous array is
passed as an argument to a routine requiring a contiguous one.

-- glen
 
J

James Kuyper

(snip)


By the way, Fortran doesn't necessarily use pass by reference.

I only mentioned Fortran as an example of a language that can pass by
reference; I didn't intend to imply that it always uses pass by
reference. I knew that it doesn't.
 
S

Shao Miller

I was asked in an interview :
What is the scope of the parameters that are passed to a function inside the function?

Sometimes interviewers don't actually know what they're talking about,
and sometimes they do but their question is misunderstood... Parameters
aren't passed to a function. Arguments are passed to a function.
Roughly speaking, the values of the arguments become the initial values
of the parameters.

To answer your question, the scope of a function's parameters depends on
whether or not the function declaration is a function definition or not.
If it's a declaration, the parameters have what's called "function
prototype scope". For example:

int add(int a, int b);

This is not a definition, so 'a' and 'b' have function prototype scope.
For ex : int add (int a, int b)
{
return (a+b);
}

This is a function definition, so 'a' and 'b' have what's called "block
scope".
here, what is the scope of a & b inside the functions ?

'a' can be used anywhere after the 'a' in 'int a' and anywhere before
the function's final '}'. 'b' can be used anywhere after the 'b' in
'int b' and anywhere before the function's final '}'. Because both
identifiers' scopes end at the same place, they are said to have the
"same scope".
I got confused with passing by value and passing by reference. Can anyone please clarify ?

This is a completely separate subject than your earlier questions. As
someone else already answered, C does not have "pass by reference". As
mentioned above, in C, you pass arguments whose values become the
initial values for the function's parameters.

Caller: Has arguments
Callee (called function): Has parameters

The two are _separate_. The called function can modify its parameters
and those modifications _do_not_ modify the caller's arguments. For
example:

void foo(void) {
int x = add(21, 21);
}

Your 'add' function above cannot modify the arguments '21' and '21'. It
can only modify its parameters 'a' and 'b'. As another example:

void bar(void) {
int i = 21;
int j = 21;
int x = add(i, j);
}

Your 'add' function above cannot modify the arguments 'i' and 'j'. It
can only modify its parameters 'a' and 'b'.
 
G

glen herrmannsfeldt

I only mentioned Fortran as an example of a language that can pass by
reference; I didn't intend to imply that it always uses pass by
reference. I knew that it doesn't.

OK, then to make sure that others also know that.

It is especially interesting now with Fortran's C interoperability
feature, such that you can call between Fortran and C.

-- glen
 
L

Les Cargill

Eric said:
`extern' and `static' do not affect the scope of an
identifier; they affect its linkage, which is a different
matter. Demonstration:

int f(void) {
extern int global(void);
return global();
}

int g(void) {
return 2 * global(); // Undefined behavior
}

Pre-ANSI compilers differed on this, but the original
ANSI Standard decided to keep the notions of "scope" and
"linkage" separate.

yeah... I was trying to avoid that hoisting the concept of
linkage in. I was using "extern" as a marker for things that
transcend lexical scope.
As a compromise and a nod to existing
implementations that did things the other way (says the
Rationale), the committee chose not to require the compiler
to diagnose the problem, but left the behavior undefined.


Perhaps, depending on what you mean by "lexical scope" (a
phrase the Standard does not use). What the Standard *does*
say is that a `static' declaration outside any block has
"file" scope (6.2.1p4) and "internal" linkage (6.2.2p3).

I could easily be wrong, but the resources I've seen in the past
equate lexical scope with file scope - although "lexical scope" can also
be a more general term ( I believe M$ says that file scope is a
specialization of lexical scope - which makes little sense to me).
As the Rationale says, "This has traditionally been a
major area of confusion."


Yep.
 
K

Keith Thompson

Les Cargill said:
I could easily be wrong, but the resources I've seen in the past
equate lexical scope with file scope - although "lexical scope" can also
be a more general term ( I believe M$ says that file scope is a
specialization of lexical scope - which makes little sense to me).

http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping
explains the distinction between lexical and dynamic scoping in a manner
that's at least consistent with my understanding of the terms.

With lexical scoping, as in C:

void foo() {
/* The name "x" is not visible here */
}

void bar() {
int x;
foo();
}

With dynamic scoping, as in some other languages, particularly some
Lisp-like languages:

void foo() {
/*
* The name "x" refers to the object of that name defined in
* bar() -- *if* foo() was called from bar().
*/
}

void bar() {
int x;
foo();
}

which would be very surprising to most C programmers.
 
L

Les Cargill

Keith said:
http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping
explains the distinction between lexical and dynamic scoping in a manner
that's at least consistent with my understanding of the terms.

With lexical scoping, as in C:

void foo() {
/* The name "x" is not visible here */
}

void bar() {
int x;
foo();
}

With dynamic scoping, as in some other languages, particularly some
Lisp-like languages:

void foo() {
/*
* The name "x" refers to the object of that name defined in
* bar() -- *if* foo() was called from bar().
*/
}

void bar() {
int x;
foo();
}

which would be very surprising to most C programmers.

interesting! Thanks, Keith. Sorry about the noise.
 
B

Ben Bacarisse

Ben Bacarisse said:
They are terms at different levels of explanation. The C standard
defines block scope as one kind of scope an identifier can have (the
others being file scope, function scope, and function parameter
scope).

Of course it's called "function *prototype* scope". Thanks to the
person who pointed this out.

<snip>
 
B

BartC

Shao Miller said:
On 2/5/2013 04:09, Esash wrote:
The two are _separate_. The called function can modify its parameters and
those modifications _do_not_ modify the caller's arguments.
... As another example:

void bar(void) {
int i = 21;
int j = 21;
int x = add(i, j);
}

Your 'add' function above cannot modify the arguments 'i' and 'j'. It can
only modify its parameters 'a' and 'b'.

It gets a bit more confusing when arrays are involved:

void iadd(int a[],int b) {
a[0]+=b;
}

int main (void) {
int x[]={10,20,30};

iadd (x,1);
}

Here, the caller's 'x' argument *is* apparently modified. In fact, an array
can *only* be passed by reference.
 
B

Ben Bacarisse

BartC said:
Shao Miller said:
On 2/5/2013 04:09, Esash wrote:
The two are _separate_. The called function can modify its
parameters and those modifications _do_not_ modify the caller's
arguments.
... As another example:

void bar(void) {
int i = 21;
int j = 21;
int x = add(i, j);
}

Your 'add' function above cannot modify the arguments 'i' and 'j'.
It can only modify its parameters 'a' and 'b'.

It gets a bit more confusing when arrays are involved:

void iadd(int a[],int b) {

There's no array here. I agree that it's confusing to people learning
C, but the confusing thing is that 'a' is not an array. It's the fact
that an array is *not* involved that is confusing.
a[0]+=b;
}

int main (void) {
int x[]={10,20,30};

iadd (x,1);

Whilst 'x' is an array, what gets passed is not.
}

Here, the caller's 'x' argument *is* apparently modified. In fact, an
array can *only* be passed by reference.

That is just going to confuse matters. C always passes by value and
arrays don't alter that. The peculiarity is best explained as (a) an
odd syntax for some pointer parameters and (b) the fact that
array-valued expressions get converted to pointers in most contexts.
 
G

glen herrmannsfeldt

James Kuyper said:
On 02/07/2013 03:28 PM, BartC wrote:
It gets a bit more confusing when arrays are involved:
void iadd(int a[],int b) {
a[0]+=b;
}
int main (void) {
int x[]={10,20,30};
iadd (x,1);
}
Here, the caller's 'x' argument *is* apparently modified. In fact, an array
can *only* be passed by reference.
In C, arrays cannot be passed, period, neither by value nor by
reference.

What about arrays inside a struct?
The parameter named 'a' is declared as if it were an array,
but such a declaration is adjusted to be the equivalent of
void iadd(int *a, int b);
While the expression iadd(x,1) looks as though it is passing an array to
a function, in this context x is automatically converted into a pointer
to the first element of the array. Pointers are passed by value. iadd
can change the value of x[0], by dereferencing that pointer.

The result looks very much the same as if C allowed the array to be
passed by reference, but that's just an illusion, and you can get very
confused if you don't understand that illusion. In particular, without
understanding that illusion, you can't correctly explain why

It gets more interesting, and more obvious that it is pass
by value, when you do something like:

void iadd(int a[],int b) {
a++;
a[0]+=b;
}


Changes to a are to the copy in iadd, changes to *a change
the array in the caller.

-- glen
 
J

James Kuyper

James Kuyper said:
On 02/07/2013 03:28 PM, BartC wrote:
It gets a bit more confusing when arrays are involved:
void iadd(int a[],int b) {
a[0]+=b;
}
int main (void) {
int x[]={10,20,30};
iadd (x,1);
}
Here, the caller's 'x' argument *is* apparently modified. In fact, an array
can *only* be passed by reference.
In C, arrays cannot be passed, period, neither by value nor by
reference.

What about arrays inside a struct?

structs containing arrays can be passed by value, which for many
purposes is equivalent to passing arrays by value. Pointers that refer
to such structs can also be passed by value, which is functionally
comparable to passing them by reference. It's only unwrapped Arrays
which can't be passed.
 

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,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top