This code causes compilation error ” error: redefinition of ‘p’ with a different type”:
void fun() {
printf("fun");
}
void (*p)();
p = &fun;
But if modify
void (*p)(); p = &fun; to
void (*p)() = &fun, everything is OK.
What’s the difference between
void (*p)(); p = &fun; and
void (*p)() = &fun?
The three prior answers do not answer the question and are incorrect when they indicate that “p = &fun;” is an assignment.
Actually, the compiler is attempting to interpret “p = &fun;” as a declaration, so “p” is a declarator, “&fun” is an initializer, and “p = &fun” forms an init-declarator (in the formal grammar of the C specification).
Having interpreted this as a declaration, the type that should be in the declaration defaults to int (for legacy reasons), so the compiler essentially sees this as “int p = &fun;”, which is a definition of p. Because p was previously defined as a pointer to a function, the compiler complains that you are redefining p with a different type.
For the language grammarians: I cannot make out how this could be a declaration in the formal grammar. A translation-unit would expand to an external-declaration, an external-declaration would expand to a declaration, and a declaration would expand to “declaration-specifiers init-declarator-list[opt];” (per 6.7 in the C standard). The declaration-specifiers appear to require at least one of the keywords involved in storage-class-specifier, type-specifier, type-qualifier, or function-specifier. No such keyword appears in the source, so this cannot be a declaration. I suspect the compiler is parsing with some grammar from before the 1999 standard, so this is legacy behavior. Nonetheless, the error message makes it clear the compiler has seen two definitions, not a definition followed by an assignment.