scope of function parameters

Discussion in 'C Programming' started by Esash, Feb 5, 2013.

  1. Esash

    Esash Guest

    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 ?
     
    Esash, Feb 5, 2013
    #1
    1. Advertising

  2. Esash

    Noob Guest

    Esash wrote:

    > 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.
     
    Noob, Feb 5, 2013
    #2
    1. Advertising

  3. Esash

    Ian Collins Guest

    Esash wrote:
    > 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?

    --
    Ian Collins
     
    Ian Collins, Feb 5, 2013
    #3
  4. Esash

    James Kuyper Guest

    On 02/05/2013 04:09 AM, Esash wrote:
    > 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.
    --
    James Kuyper
     
    James Kuyper, Feb 5, 2013
    #4
  5. Esash

    Chad Guest

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


    Chad
     
    Chad, Feb 5, 2013
    #5
  6. Esash

    Les Cargill Guest

    Chad wrote:
    > 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.

    --
    Les Cargill
     
    Les Cargill, Feb 5, 2013
    #6
  7. Esash

    Eric Sosman Guest

    On 2/5/2013 8:29 AM, Les Cargill wrote:
    > Chad wrote:
    >> Is block scope the same as lexical scope? If not, then what's the
    >> difference.

    >
    > 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."

    --
    Eric Sosman
    d
     
    Eric Sosman, Feb 5, 2013
    #7
  8. Chad <> writes:

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

    --
    Ben.
     
    Ben Bacarisse, Feb 5, 2013
    #8
  9. James Kuyper <> wrote:

    (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
     
    glen herrmannsfeldt, Feb 5, 2013
    #9
  10. Esash

    James Kuyper Guest

    On 02/05/2013 11:51 AM, glen herrmannsfeldt wrote:
    > James Kuyper <> wrote:
    >
    > (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.


    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.
     
    James Kuyper, Feb 5, 2013
    #10
  11. Esash

    Shao Miller Guest

    On 2/5/2013 04:09, Esash wrote:
    > 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'.

    --
    - Shao Miller
    --
    "Thank you for the kind words; those are the kind of words I like to hear.

    Cheerily," -- Richard Harter
     
    Shao Miller, Feb 5, 2013
    #11
  12. James Kuyper <> wrote:
    > On 02/05/2013 11:51 AM, glen herrmannsfeldt wrote:
    >> James Kuyper <> wrote:


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


    > 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
     
    glen herrmannsfeldt, Feb 5, 2013
    #12
  13. Esash

    Les Cargill Guest

    Eric Sosman wrote:
    > On 2/5/2013 8:29 AM, Les Cargill wrote:
    >> Chad wrote:
    >>> Is block scope the same as lexical scope? If not, then what's the
    >>> difference.

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


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


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

    >> Your mileage may vary.

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



    Yep.

    --
    Les Cargill
     
    Les Cargill, Feb 5, 2013
    #13
  14. Les Cargill <> writes:
    [...]
    > 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.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Feb 6, 2013
    #14
  15. Esash

    Les Cargill Guest

    Keith Thompson wrote:
    > Les Cargill <> writes:
    > [...]
    >> 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.
    >


    interesting! Thanks, Keith. Sorry about the noise.

    --
    Les Cargill
     
    Les Cargill, Feb 6, 2013
    #15
  16. Ben Bacarisse <> writes:
    <snip>
    > 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>
    --
    Ben.
     
    Ben Bacarisse, Feb 6, 2013
    #16
  17. Esash

    BartC Guest

    "Shao Miller" <> wrote in message
    news:kerts4$1hk$...
    > On 2/5/2013 04:09, Esash wrote:


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


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

    --
    Bartc
     
    BartC, Feb 7, 2013
    #17
  18. "BartC" <> writes:

    > "Shao Miller" <> wrote in message
    > news:kerts4$1hk$...
    >> On 2/5/2013 04:09, Esash wrote:

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

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

    --
    Ben.
     
    Ben Bacarisse, Feb 7, 2013
    #18
  19. James Kuyper <> wrote:
    > 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
     
    glen herrmannsfeldt, Feb 7, 2013
    #19
  20. Esash

    James Kuyper Guest

    On 02/07/2013 05:10 PM, glen herrmannsfeldt wrote:
    > James Kuyper <> wrote:
    >> 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.
     
    James Kuyper, Feb 7, 2013
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jason
    Replies:
    2
    Views:
    514
    Jonathan Mcdougall
    May 13, 2006
  2. Henry Olders

    scope of function parameters

    Henry Olders, May 29, 2011, in forum: Python
    Replies:
    21
    Views:
    497
  3. Wolfgang Rohdewald

    Re: scope of function parameters

    Wolfgang Rohdewald, May 29, 2011, in forum: Python
    Replies:
    8
    Views:
    232
    Chris Angelico
    May 29, 2011
  4. Henry Olders
    Replies:
    2
    Views:
    406
    Thomas Rachel
    May 31, 2011
  5. Andrew Falanga
    Replies:
    2
    Views:
    202
    Andrew Falanga
    Nov 22, 2008
Loading...

Share This Page