Why are typedef identifiers allowed to be declared multiple times?

后端 未结 3 1152
醉梦人生
醉梦人生 2020-12-05 15:41

From the C99 standard, 6.7(5):

A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a d

相关标签:
3条回答
  • 2020-12-05 16:09

    For the same reason that other declarations are allowed to be declared multiple times. For example:

    void foo(int a);
    
    void foo(int a);
    
    int main()
    {
        foo(42);
    }
    
    void foo(int a)
    {
        printf("%d\n", a);
    }
    

    This allows more than one header to declare a function or structure, and allow two or more such headers to be included in the same translation unit.

    typedefs are similar to prototyping a function or structure -- they declare identifiers that have some compile time meaning, but no runtime meaning. For example, the following wouldn't compile:

    int main()
    {
        typedef int x;
        typedef int x;
        x = 42;
    }
    

    because x does not name a variable; it is only a compile time alias for the name int.

    0 讨论(0)
  • 2020-12-05 16:13

    Your program compiles without error because your compiler is being lax (or compiling for a different standard). If I compile your code with gcc 4.4.7 then it in fact does report an error about the redefinition of x.

    0 讨论(0)
  • 2020-12-05 16:27

    C99 is different from C11

    The rules change between C99 and C11 (and the C11 rules match the C++ rules, as I understand it). Note that in both standards, ¶3 is in the Constraints section and ¶5 is in the Semantics section. That is important for error messages — constraint violations require a diagnostic.

    ISO/IEC 9899:1999 §6.7 Declarations

    ¶3 If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except for tags as specified in 6.7.2.3.

    5 A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that:

    • for an object, causes storage to be reserved for that object;
    • for a function, includes the function body;98)
    • for an enumeration constant or typedef name, is the (only) declaration of the identifier.

     

    ISO/IEC 9899:2011 §6.7 Declarations

    ¶3 If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that:

    • a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;
    • tags may be redeclared as specified in 6.7.2.3.

    ¶5 A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that:

    • for an object, causes storage to be reserved for that object;
    • for a function, includes the function body;119)
    • for an enumeration constant, is the (only) declaration of the identifier;
    • for a typedef name, is the first (or only) declaration of the identifier.

    Lundin noted that the Standard C Committee's web site contains n1360, a one page document detailing why this change was made. Basically: C++ does it; some compilers already do it; it is neither hard to do nor subverting anything to permit (require) it.

    GCC doesn't always enforce the standard

    If your code is compiling, then it is being compiled under the C11 rules, or C++ rules. It is not being compiled under (strict) C99 rules.

    Note that sufficiently recent versions of GCC allow the redefinition unless you insist otherwise, but also note the report by John Bollinger that GCC 4.4.7 (on an unidentified platform) does not allow the redefinition at all in C99 mode.

    Consider the file retypedef.c:

    int main(void)
    {
        typedef int x;
        typedef int x;
        x y = 0;
        return y;
    }
    

    Compiling on Mac OS X 10.9.5 with GCC 4.9.1, I get:

    $ gcc -O3 -g -std=c11 -Wall -Wextra -Werror           -c retypedef.c
    $ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -pedantic -c retypedef.c
    $ gcc -O3 -g -std=c99 -Wall -Wextra -Werror           -c retypedef.c
    $ gcc -O3 -g -std=c99 -Wall -Wextra -Werror -pedantic -c retypedef.c
    retypedef.c: In function ‘main’:
    retypedef.c:4:17: error: redefinition of typedef ‘x’ [-Werror=pedantic]
         typedef int x;
                     ^
    retypedef.c:3:17: note: previous declaration of ‘x’ was here
         typedef int x;
                     ^
    cc1: all warnings being treated as errors
    $
    

    It doesn't complain unless -pedantic is used, and then only if C99 is requested (it is standard compliant to redefine a typedef in the same scope in C11).

    0 讨论(0)
提交回复
热议问题