arrays that are not lvalues and sequence point restriction

后端 未结 1 1159
囚心锁ツ
囚心锁ツ 2021-02-10 04:30

In ISO C99, arrays that are not lvalues still decay to pointers, and may be subscripted, although they may not be modified or used after the next sequence point. (source)

<
相关标签:
1条回答
  • 2021-02-10 05:19

    Note, the text OP quoted is from GCC documentation. Relevant text from C99 to back up that quote is:

    C99 6.5.2.2/5

    If an attempt is made to modify the result of a function call or to access it after the next sequence point, the behavior is undefined.

    and also from the list of changes in the Foreword:

    conversion of array to pointer not limited to lvalues

    I don't have the C89 text to compare, but the C99 description of array-to-pointer conversion (6.3.2.1/3) does not mention any restriction on the array being an lvalue. Also, the C99 section on subscripting (6.5.2.1/2) talks about the expression being subscripted as postfix expression, it does not mention lvalues either.


    Consider this code:

    struct foo
    {
         char buf[20];
    };
    
    struct foo foo(char const *p) { struct foo f; strcpy(f.buf, p); return f; }
    
    int main()
    {
         char *hello = foo("hello").buf;
         char *bye = foo("bye").buf;
    
         // other stuff...
    
         printf("%s\n", hello);
         printf("%s\n", bye);
    }
    

    Where do the pointers hello and bye point to? The purpose of this clause is to say that the compiler does not have to keep all of the returned objects hanging around in memory somewhere in order to make those pointers remain valid indefinitely.

    Instead, the hello is only valid up until the next ; in this case (or next sequence point in general). This leaves the compiler free to implement returning structs by value as a hidden pointer parameter, as Chris Torek describes in his excellent post, which can be "freed" at the end of the current statement.

    NB. The C99 situation isn't quite as simple as described in Chris's post, as the following has to work:

    printf("%s %s\n", foo("hello").buf, foo("bye").buf);
    

    My install of gcc 4.8 seems to get it right though - that works with -std=c99, and segfaults with -std=c89.

    0 讨论(0)
提交回复
热议问题