Zilog support has claimed that it is in fact not a compiler bug, and that the original code does not compile as it is not strictly ANSI C. It is accepted by GCC because the compiler is "lenient" and has added a few more syntax rules that go beyond ANSI C specification. Here is the full response:
The GCC compiler, while very good, is not necessarily a perfect
implementation of the C Standard. Over the years I have seen a few
cases where widely used compilers, like MSVC++ and, less frequently,
GCC accept syntax that is not strictly ANSI C when that syntax seems
to be a harmless quasi-extension of standard C and there’s no danger
of its being interpreted in some alternate, legitimate meaning. This
may be another instance of that.
There’s a fine point of C syntax involved and here is my understanding
of that point, along with why perhaps GCC allows the customer’s
original syntax. Once a function pointer, e.g. a properly defined
variable fnPtr, has acquired a definition, it is allowed to invoke it
without the preceding * indirection operator through an expression
like
result = fnPtr(x); // This is legal syntax…
result = (*fnPtr) (x); // … even though this is “more correct”
The reason why the 1st syntax shown above is allowed is that the
parentheses enclosing parameter x are regarded as a C operator whose
type is “pointer to function”. So the presence of those parentheses
makes the indirection operator unnecessary when the function pointer
is actually used for making a function call. However, in a case like
this customer code where you are just using the function pointer in an
assignment statement, this doesn’t come into play and so those
operands are not, in fact, strictly assignment compatible. However, a
user who is not an expert language wrangler can hardly be blamed for
expecting that if the function pointer can be used without the * in
one place, it should also be acceptable in other contexts. This might
be why the GCC developers have apparently decided to accept the user’s
syntax.
Here is an alternate version that compiles:
struct something {
char *(*choices[2]);
};
char* arr[2] = {"foo", "bar"};
int main(void) {
struct something obj;
*obj.choices = &arr;
return 0;
}
memcpy
? If onlysizeof(char*(*)[2]) == sizeof(void*)
you couldvoid *val = &arr; memcpy(&obj.choices, &val, sizeof(void*))
. – Satan