I have written the following code:
unsigned char *cPtr[] =
{
"First",
"Second",
"Third"
};
typedef struct
{
int a;
char *lut; /* or char lut[20]*/
}Grp_t;
const Grp_t Grp_st[]=
{
{ 0, cPtr[0] },
{ 1, cPtr[1] },
{ 2, cPtr[2] }
};
When I try to compile this code I got the following error:
error: initializer element is not constant
error: (near initialization for 'Grp_st[0].lut[0]')
But when I replace *cPtr[]
by cPtr[][16]
as
unsigned char cPtr[][16] =
{
"First",
"Second",
"Third"
};
I am able to successfully compile the code.
Please can any one explain me the concept which I am missing here.
It is the limitation of C.
6.7.8.4 Initialization:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
And 6.6.9 Constant expressions:
An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator; it shall be created explicitly using the unary & operator or an integer constant cast to pointer type, or implicitly by the use of an expression of array or function type. The array-subscript [] and member-access . and -> operators, the address & and indirection * unary operators, and pointer casts may be used in the creation of an address constant, but the value of an object shall not be accessed by use of these operators.
If you can change the code to make Grp_st
not of static storage duration it compiles:
#include <stdio.h>
const char *cPtr[] =
{
"First",
"Second",
"Third"
};
typedef struct
{
int a;
const char *lut;
} Grp_t;
int main(void) {
Grp_t Grp_st[]= {
{ 0, cPtr[0] },
{ 1, cPtr[1] },
{ 2, cPtr[2] }
};
return 0;
}
In the second case you managed to compile the code because you didn't access array element at given index, but only a pointer (in case of char cPtr[][16]
, the cPtr[0]
gives address of the first array of 16 characters and cPtr[0]
decays to type char *
in expression) - therefore you didn't violate the 6.6.9 rule.
Initializer for a static object must be constant1.
Since you're trying to initialize a member of a static object, the member having the type pointer to char, you need an address constant2.
cPtr[0]
is not an address constant because the value of the object cPtr
is accessed while trying to create this address constant3.
On the other hand, cStr[0]
doesn't access any value of the object cStr
. The expression cStr[0]
is identical to &cStr[0][0]
, which clearly doesn't access the value, but only the address to that value.
1 (Quoted from: ISO/IEC 9899:201x 6.7.9 Initialization 4)
All the expressions in an initializer for an object that has static or thread storage duration
shall be constant expressions or string literals.
2 (Quoted from: ISO/IEC 9899:201x 6.6 Constant expressions 9)
An address constant is a null pointer, a pointer to an lvalue designating an object of static
storage duration, or a pointer to a function designator; it shall be created explicitly using
the unary & operator or an integer constant cast to pointer type, or implicitly by the use of
an expression of array or function type. The array-subscript [] and member-access .
and -> operators, the address & and indirection * unary operators, and pointer casts may
be used in the creation of an address constant, but the value of an object shall not be
accessed by use of these operators.
3 but the value of an object shall not be accessed by use of these operators.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With