Question regarding static

Discussion in 'C Programming' started by somenath, Feb 17, 2014.

  1. somenath

    somenath Guest

    I am not able to understand why the following program is not throwing error.

    #include<stdio.h>
    static int i;
    foo ()
    {
    static int i;
    }

    int main(void)
    {
    return 0;
    }

    According to my understanding both the i have local linkage so object having same linkage defined twice. If this is correct then should not the compiler throw error?

    -
    Somenath
     
    somenath, Feb 17, 2014
    #1
    1. Advertisements

  2. somenath

    JohnF Guest

    I think you could have answered your own question
    if you'd tried just a little harder.
    Compile and run the following. Now what do you think?...

    #include <stdio.h>
    static int i=0;
    int foo () {
    static int i=0;
    i = i%3 + 1;
    return i; }
    int main (void) {
    int foo(), n=0;
    for ( n=1; n<=15; n++ ) {
    i = i%2 + 1;
    printf("%3d: imain=%d, ifoo=%d\n",n,i,foo()); }
    return 0; }
     
    JohnF, Feb 17, 2014
    #2
    1. Advertisements

  3. somenath

    BartC Guest

    Both 'i' variables have space reserved in the same region. But the name of
    'i' in foo() is local to that function, and it hides the outer 'i'. So there
    is no clash in names that would be an error.
     
    BartC, Feb 17, 2014
    #3
  4. somenath

    somenath Guest


    As I understand main refer to the file scope i and foo refer to the i local to itself.
    So imain have the value between 1 and 2 because of the expression i = i%2 + 1; and foo return i between 1 and 3 because of the expression i = i%3 + 1;

    But I was confused as both the i have local linkage so both will be stored in same region of memory then how C compiler avoids saying both i is same.

    After reading Bart's article I came to know that in spite of the fact they gets placed in same region they will be hidden
    to each other.

    So do get my understanding little better I did this in linux environment

    gcc test.c -o test

    readelf -s test

    41: 0000000000600954 4 OBJECT LOCAL DEFAULT 24 i
    42: 0000000000600958 4 OBJECT LOCAL DEFAULT 24 i.2126

    Now I think I understand that C compiler encode i differently and put in same region of memory. Is my understanding correct?
    But how does C compiler learn about scope?
     
    somenath, Feb 17, 2014
    #4
  5. somenath

    James Kuyper Guest

    The first 'i' has file scope, the second one has block scope associated
    with the outermost block of foo(). Because they have different scopes,
    they are different variables with the same name. Within foo, after the
    second declaration of 'i', all uses of 'i' refer to that one; it's
    declaration hides the file scope declaration of 'i'.
     
    James Kuyper, Feb 17, 2014
    #5
  6. There is one case where Java doesn't allow two variables with the
    same name, but I forget if C has this restriction:

    int i;
    for(int i=0;i<10;i++) ;

    Even though the second i is local to the loop, you can't have one
    if there is one in the outer block. (You can still have class (static)
    variables and instance variables with the same name, though.)

    -- glen
     
    glen herrmannsfeldt, Feb 17, 2014
    #6
  7. somenath

    Eric Sosman Guest

    Several responders have assured you that the two `i' have
    different scopes and are different variables, but I haven't seen
    anyone address the matter of linkage. "Linkage" is the mechanism
    by which identifiers in distinct scopes denote the same object or
    function. Scope is not the be-all and end-all of "identity," as
    you can see in this example:

    int foo(void) {
    extern int x;
    return ++x;
    }

    int bar(void) {
    extern int x;
    return x--;
    }

    The two `x' have different scopes, yet they refer to the same
    variable because of their linkage. (I don't recommend this style,
    by the way, but it's legal.)

    Back to your example: The first `i', the one at file scope,
    has internal linkage as you say (this is spelled out in 6.2.2p3).
    But the `i' at block scope does *not* have internal linkage;
    it has "none" linkage (6.2.2p6), and therefore names a variable
    that is distinct from all others (6.2.2p2). And that is why you
    have not defined the same object twice, and why the compiler is
    happy with your code.
     
    Eric Sosman, Feb 17, 2014
    #7
  8. somenath

    James Kuyper Guest

    When allowing a declaration in the first part of an if statement was
    first proposed, the appropriate scope of that variable was hotly
    debated. One option was putting it in the scope of the enclosing block,
    which would have prohibited such code. The final decisions was that the
    scope of such variables is "the remainder of the declaration and the
    entire loop, including the other two expressions;" (6.8.5.3p1) so the
    two 'i's have different scope. They are therefore two different
    variables, so the declarations do not violate a constraint.
     
    James Kuyper, Feb 17, 2014
    #8
  9. (snip, I wrote)
    As well as I know it, in Java they are different scope, but it still
    disallows it.

    That is, you can either have i as a local (method) variable, or declare
    one on each for loop, but not both. If you need the value after
    the loop, then you have to use the outer declaration.

    (Where I said i, that is any variable used in a for loop.)

    Seems to me that Java tries to fix some of the problems that
    C programs can have, without making it too hard for C programmers
    to learn and use.

    While using the same variable name at file scope and inside a function
    can be confusing (and lead to bugs) using the same variable name
    in a loop to refer to a different variable is more likely to lead
    to bugs.

    Another interesting Java change is no comma operator, but instead
    it is part of the syntax of the for loop, such that the common C
    usage still works.

    -- glen
     
    glen herrmannsfeldt, Feb 18, 2014
    #9
  10. somenath

    somenath Guest

    So depending upon the scope of the variable does static key word has different meaning?
    Then is my following understanding correct ?

    1) If it is associated with a variable inside function
    i.e the variable has automatic storage duration as below
    foo() {
    int x;
    }
    The static provide the variable x static storage duration but it does not provide any linkage to x.

    2) If it is associated with a variable outside function that has external linkage
    /*file.c/
    int x

    The keyword static here does not provide static storage duration as the variable x already has static storage duration. Here it provides internal linkage.

    So in essence static mainly provide static storage duration who needs it but it provide local linkage who has already static storage duration.

    Why C has different meaning for same keyword? is it for minimizing the number of keyword ?
     
    somenath, Feb 18, 2014
    #10
  11. somenath

    somenath Guest


    Also I do not have a very clear distinction between internal linkage andno linkage.
    According to my understanding linkage is a way to identify the connection between identifiers in separate file .
    If the situation is as follows
    1.c
    +++++
    #include<stdio.h>
    int i;
    int main(void)
    {
    printf("\n value of i = %d\n",i);

    return 0;
    }
    +++++++
    2.c
    int i =5;
    +++++
    Now if these two files are compiled and linked the output will be
    value of i = 5

    So in this case in file 1.c i has the external linkage and which refer to the same i defined in 2.c

    Now if I change 1.c as follows

    #include<stdio.h>
    static int i;
    int main(void)
    {
    printf("\n value of i = %d\n",i);

    return 0;
    }

    the output is
    value of i = 0

    Here i has internal linkage and also by default in C static variable is initialized so i is initialized to 0 .

    Now if I change 1.c as follows
    #include<stdio.h>
    int main(void)
    {
    static int i;
    printf("\n value of i = %d\n",i);

    return 0;
    }

    Now i has no linkage and initializes to 0. So the output is
    value of i = 0
    So the output is same for the case of internal and no linkage. My question is what is the significance of internal linkage ? Is it a way of saying that in a particular file if an identifier has internal linkage then that identifier only can be referred in that file . If the identifier has no linkage then if the identifier goes out of scope it can no longer be referred.

    So for example
    #include<stdio.h>
    static int i =15;
    int main(void)
    {
    extern int i;
    printf("\n value of i = %d\n",i);

    return 0;
    }
    Here i has internal linkage but it can be referred from the same file. extern int i; is referring to static int i =15;
    So here the output will be
    value of i = 15

    Now in the following case

    #include<stdio.h>
    static int i =15;
    void foo()
    {
    int x =20;
    }
    int main(void)
    {
    extern int i;
    printf("\n value of i = %d\n",i);

    return 0;
    }

    i has no linkage in foo() so there is no way it can be referred to from outside foo() . So extern int i; refer to static int i =15; only.

    So if this is only difference between no linkage and internal linkage?
     
    somenath, Feb 18, 2014
    #11
  12. somenath

    James Kuyper Guest

    On 02/17/2014 08:04 PM, somenath wrote:
    ....
    The parts where you use "who" aren't quite correctly worded - I'm not
    sure what you meant, so I'm not sure how to correct them. I'll just
    provide my own statement, and you can tell me if it matches your
    understanding.

    At block scope, 'static' gives "static storage duration". However, at
    file scope, all objects already have static storage duration, so
    'static' is given an entirely different meaning: "internal linkage".

    Re-using the keyword for unrelated purposes was a bad decision made
    early in the development of C, or possibly even in it's predecessor
    languages. It cannot be changed now without breaking a lot of existing
    code. You'd think the committee had learned from that lesson, but they
    added a third, completely unrelated meaning for static in C99:

    int func( int array[static 32]);

    In this case, 'static' means that it is undefined behavior to call
    func() with an argument that does not point at an element of an array
    with at least 32 accessible members.
     
    James Kuyper, Feb 18, 2014
    #12
  13. somenath

    Eric Sosman Guest

    Yes. See the cited sections of the Standard
    Right. More precisely, it gives the identifier "none" linkage.
    Not possible. If the identifier is declared with `static', it
    cannot have external linkage.
    I see no "static here." If the declaration were `static int x;'
    at file scope, then yes: It would have static storage duration anyhow
    (by virtue of being at file scope), and adding `static' means only
    that it has internal rather than external linkage.
    I can't find the exact quote, but somebody observed that "It
    wouldn't be a new C Standard if it didn't invent a new meaning
    for `static'." That is, there are even more uses for `static'
    than those you've found thus far ...

    (The `static' keyword is hardly the only "overloaded" keyword
    in the language. See also `while', `long', `void', ... All of
    which have different meanings in different contexts.)
     
    Eric Sosman, Feb 18, 2014
    #13
  14. somenath

    James Kuyper Guest

    "In the set of translation units and libraries that constitutes an
    entire program, each declaration of a particular identifier with
    external linkage denotes the same object or function. Within one
    translation unit, each declaration of an identifier with internal
    linkage denotes the same object or function. Each declaration of an
    identifier with no linkage denotes a unique entity." (6.2.2.p2)

    So the key distinction between internal linkage and no linkage is
    whether multiple declarations can refer to the same object or function.
    It's more precisely about scopes than about files; file scope is one
    kind of scope, which is how files enter into it. "An identifier declared
    in different scopes or in the same scope more than once can be made to
    refer to the same object or function by a process called linkage." (6.2.2p1)
    The following 'i's have no linkage, so each one identifies a different
    object. Having multiple declarations is allowed only because each one
    has a different scope:

    int foo()
    {
    int i;
    {
    int i;
    }
    }
    int bar() { int i; }

    The following 'i's, declared at file scope, have internal linkage, so
    they both identify the same object:

    static int i;
    static int i=2;

    ....
    That is another consequence of that distinction.
     
    James Kuyper, Feb 18, 2014
    #14
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.