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".
"0"is an array with static storage duration. Braced lists aren't objects of any sort (they only provide initial values for whatever you are initializing)