Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redefinition of typedef

Tags:

I am possibly doing this incorrectly and this is much a question about why it works in one compiler and not the other.

I have a large C application, and I am trying to follow the style of not including header files from within other header files. Instead, using forward declarations; thus I am trying the following.

// in A.h typedef struct A_ A; typedef struct B_ B; struct A_ {     double a;     B *b; };  // in B.h typedef struct B_ B; struct B_ {     int c; };  // in C.h typedef struct A_ A; typedef struct B_ B; void function_do_something(A*, B*);  // in C.c #include "A.h" #include "B.h" #include "C.h" void function_do_something(A* a, B* b) {     ... } 

This paradigm compiles and runs in Ubuntu 11.10 gcc -- but it gives compiler erros in OpenSUSE gcc that say "redefinition of typedef".

I have been doing my development in Ubunutu and so hadn't realised that this paradigm might be incorrect. Is it just that this is plain wrong and Ubuntu's gcc is being too nice?

like image 778
BrT Avatar asked Dec 03 '11 12:12

BrT


People also ask

Can you redefine typedef?

Using typedef redeclaration, you can redefine a name that is a previous typedef name in the same scope to refer to the same type. For example: typedef char AChar; typedef char AChar; The typedef redeclaration feature can be enabled by any extended language level.

How do I override typedef?

You can override (localize) typedef by moving them into the class. But C++ requires virtual functions to have the same signature and the return type is part of the signature.

What does redefinition mean in C++?

A redefinition is an attempt to redefine the same variable, e.g.: int a = 5; int a = 6; Also. int foo(); is not a definition. It's a declaration.


2 Answers

I was surprised by this because I'm fairly sure that redeclaring the same typedef in the same scope is legal in C++, but apparently it is not legal in C prior to the 2011 standard.

First, typedef names have no linkage:

ISO/IEC 9899:1999 + TC3 6.2.6/6:

The following identifiers have no linkage: an identifier declared to be anything other than an object or a function [...]

and 6.7/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.

So you need to ensure that each typedef declaration appears only once at file scope in each translation unit.

The 2011 C standard allows redeclaration of typedef names. 6.7 3 says:

… a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;…

like image 136
CB Bailey Avatar answered Sep 26 '22 21:09

CB Bailey


One piece of the idiom is missing. The forward declarations are independent from the definitions, so they should be in a separate header file.

// a_fwd.h  #ifndef A_FWD_H #define A_FWD_H  typedef struct A_ A;  #endif  // a.h  #ifndef A_H #define A_H  #include "a_fwd.h"  struct A_ { };  #endif 

Now it's always safe to include any headers in any order.


It is illegal to have two definitions of anything. A typedef is a definition, not just a declaration, so the one compiler was being quite lax to allow the redundancy.

like image 42
Potatoswatter Avatar answered Sep 23 '22 21:09

Potatoswatter