Home > Software engineering >  Why do strings work, but character and int arrays do not work in a pointer array?
Why do strings work, but character and int arrays do not work in a pointer array?

Time:10-17

I understand if I add the arrays, st and st2, to give it space in the memory, and then add it to the pointer array, it shouldn't be a problem:

/* works */
int st[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int st2[]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
int *day_tab[]= {
        st,
        st2
};

But without first giving it space in memory, why do strings specifically work? The code below gives an error:

int *day_tab[]= {
        {0,31,28,31,30,31,30,31,31,30,31,30,31},
        {0,31,29,31,30,31,30,31,31,30,31,30,31}
};

so does the code below:

char *day_tab[]= {
        {'0','1','\0'},
        {'0','1','\0'}
};

but the code below works

char *day_tab[]= {
        "01",
        "01"
};

CodePudding user response:

This

int st[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int st2[]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
int *day_tab[]= {
        st,
        st2
};

Is three arrays: two of integers (with their own storage), and one array of two elements which are pointers to the first two arrays.

However, this is not valid:

int *day_tab[]= {
        {0,31,28,31,30,31,30,31,31,30,31,30,31},
        {0,31,29,31,30,31,30,31,31,30,31,30,31}
};

As before you have declared an array of pointers to integers, but pointers to what? Those braced lists are not storage locations, they cannot be pointed to.

Your final example is basically valid but dangerous:

char *day_tab[]= {
        "01",
        "01"
};

It is an array of two pointers to characters, and those pointers are initialized with string literals. String literals are very special in that they are actually stored somewhere, usually in read-only memory, and they can be shared (so the "01" string used twice can be stored just once). Braced lists don't have this feature in C, it's only for string literals.

The reason the final code is dangerous is that it is char* not const char*. The non-const type is accepted for reasons of backward compatibility but is not a good idea because modifying the data in a literal string is not allowed. So you're setting yourself up for a potential disaster if you actually use those pointers to write to the "01" string storage.

CodePudding user response:

The following works

int *day_tab[]= {
        st,
        st2
};

because when you access an array, it is converted to a pointer to first element (there are few exceptions to this rule). So, when you used st and st2 array in initialisation, they will convert to pointer to first element of respective array and , after initialisation, pointer day_tab[0] will point to first element of array st and pointer day_tab[1] will point to first element of array st1.

In the code snippet

int *day_tab[]= {
        {0,31,28,31,30,31,30,31,31,30,31,30,31},
        {0,31,29,31,30,31,30,31,31,30,31,30,31}
};

and

char *day_tab[]= {
        {'0','1','\0'},
        {'0','1','\0'}
};

you are trying to initialise the pointers of array day_tab with more than one initialiser. Note that pointers are scalar types and from C11 Standard#6.7.9p11

11 The initializer for a scalar shall be a single expression, optionally enclosed in braces....

However, you can use the compound literal to initialise the pointers of day_tab int pointer array, like this:

    int *day_tab[]= {
        (int []){0,31,28,31,30,31,30,31,31,30,31,30,31},
        (int []){0,31,29,31,30,31,30,31,31,30,31,30,31}
    };

This will initialise the pointers day_tab[0] and day_tab[1] to point to the first element of respective array. Similarly, for char pointers array, you can do

    char *day_tab[]= {
        (char []){'0','1','\0'},
        (char []){'0','1','\0'}
    };

When you do

char *day_tab[]= {
        "01",
        "01"
};

It works because string literals are array of characters and when it is used in the expression it will convert to pointer to type char that point to first element of array. So, this initialises the pointers day_tab[0] and day_tab[1] to point to the first element of read only string literal "01".

  • Related