Search code examples
carraysgcclvaluec89

A legal array assignment. Is it possible?


After reading the chapter about structures in the K&R book I decided to make some tests to understand them better, so I wrote this piece of code:

#include <stdio.h>
#include <string.h>

struct test func(char *c);

struct test
{
    int i ;
    int j ;
    char x[20];
};

main(void)
{
    char c[20];
    struct  {int i ; int j ; char x[20];}  a = {5 , 7 , "someString"} , b; 
    c = func("Another string").x;
    printf("%s\n" , c);
}

struct test func(char *c)
{
    struct test temp;
    strcpy(temp.x , c);
    return temp;    
}

My question is: why is c = func("Another string").x; working (I know that it's illegal, but why is it working)? At first I wrote it using strcpy() (because that seemed the most logical thing to do) but I kept having this error:

structest.c: In function ‘main’:
structest.c:16:2: error: invalid use of non-lvalue array

Solution

  •     char c[20];
        ...
        c = func("Another string").x;
    

    This is not valid C code. Not in C89, not in C99, not in C11.

    Apparently it compiles with the latest gcc versions 4.8 in -std=c89 mode without diagnostic for the assignment (clang issues the diagnostic). This is a bug in gcc when used in C89 mode.

    Relevant quotes from the C90 Standard:

    6.2.2.1 "A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type. and if it is a structure or union. does not have any member (including. recursively, any member of all contained structures or unions) with a const-qualified type."

    and

    6.3.16 "An assignment operator shall have a modifiable lvalue as its left operand."

    6.3.16 is a constraint and imposes at least for gcc to issue a diagnostic which gcc does not, so this is a bug.