char a = 0;
char b[20] = {0};
char c[][20] = {{0}};
const char *aPtr;
const char *bPtr;
const char (*cPtr)[20];
char (*dPtr)[20];
void test(void)
{
aPtr = &a;
bPtr = b;
dPtr = &b;
dPtr = c;
cPtr = c; // warning here
}
cPtr = &c; Only this line of code generated a warning.
../source/bsw/user/PackParam_user.c:21:10: warning: assignment from incompatible pointer type
cPtr = c;
^
I would like to understand why this warning occurred for this specific line of code, while the other assignment statements do not trigger any warnings.
I use gcc v4.9
This compiler message is due to a defect in the C standard relating to
constfor arrays versus their elements.When assigning a pointer to another pointer, and neither points to
voidwith or without qualifiers, the constraint in C 2018 6.5.16.1 1 is:In
cPtr = c;,chas typechar [1][20], and it is automatically converted to a pointer to its first element, so the resulting type ischar (*)[20]. It is a pointer to typechar [20].cPtrhas typeconst char (*)[20]. It is a pointer toconst char [20].C 2018 6.7.6.2 6 tells us “For two array types to be compatible, both shall have compatible element types…” But the element types,
const charandcharare not compatible, because 6.7.3 11 says “For two qualified types to be compatible, both shall have the identically qualified version of a compatible type…” Sochar [20]andconst char [20]are not compatible types.Now you might say that
const char [20]has all the qualifiers ofchar [20], and the assignment constraint allows assignment of pointers if they point to compatible types except the operand’s pointed-to type has more qualifiers. However, theconstmodifies the element type,char, not the pointed-to type, array of 20char. The constraint would allow assigning “pointer to array of 20char” to “pointer toconstarray of 20char.” But those are not the types involved.They should be the types involved. This is a defect in the C standard. An array of 20
const charshould be the same as aconstarray of 20char. If the array elements areconst, the array itself is actuallyconsttoo—any attempt to modify the array is an attempt to modify its elements and vice-versa. The array is its elements, so the identifiers of the array and the elements ought to be one single thing. But writing rules for this is complicated, and it was not done in the C standard up to 2018.The C standard has some attempt to deal with qualifiers on arrays. You could attempt to make
cPtra pointer to aconstarray of 20charby using atypedef:typedef char CharArray[20]; const CharArray *cPtr;. However, C 2018 6.7.3 10 magics this qualifier away, moving it from the array to the elements: “If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type…” In retrospect, that was insufficient, as it does not solve the problems with array qualifiers.Compiler writers are aware this is a defect in the standard, and they try to work around it, which is why GCC was modified not to give this warning unless specifically requested with
-pedantic.