So, as far as I know, this is legal in C:
foo.c
struct foo { int a; };
bar.c
struct foo { char a; };
But the same thing with functions is illegal:
foo.c
int foo() { return 1; }
bar.c
int foo() { return 0; }
and will result in linking error (multiple definition of function foo
).
Why is that? What's the difference between struct names and function names that makes C unable to handle one but not the other? Also does this behavior extend to C++?
The scope of struct type definitions ( with or without the use of typedef ) follows the same rules as variable declarations. Obviously this means that the struct definition must be within scope before variables of that type can be declared.
No, you can't. Structs can only contain variables inside, storing function pointers inside the struct can give you the desired result.
1. Member functions inside the structure: Structures in C cannot have member functions inside a structure but Structures in C++ can have member functions along with data members.
Their intent tends to be different, as revealed by their names: structs are for structured collections of data, while dictionaries are for long lists of named elements.
Why is that?
struct foo { int a; };
defines a template for creating objects. It does not create any objects or functions. Unless struct foo
is used somewhere in your code, as far as the compiler/linker is concerned, those lines of code may as well not exist.
Please note that there is a difference in how C and C++ deal with incompatible struct
definitions.
The differing definitions of struct foo
in your posted code, is ok in a C program as long as you don't mix their usage.
However, it is not legal in C++. In C++, they have external linkage and must be defined identically. See 3.2 One definition rule/5 for further details.
The distinguishing concept in this case is called linkage.
In C struct, union or enum tags have no linkage. They are effectively local to their scope.
6.2.2 Linkages of identifiers
6 The following identifiers have no linkage: an identifier declared to be anything other than an object or a function; an identifier declared to be a function parameter; a block scope identifier for an object declared without the storage-class specifierextern
.
They cannot be re-declared in the same scope (except for so called forward declarations). But they can be freely re-declared in different scopes, including different translation units. In different scopes they may declare completely independent types. This is what you have in your example: in two different translation units (i.e. in two different file scopes) you declared two different and unrelated struct foo
types. This is perfectly legal.
Meanwhile, functions have linkage in C. In your example these two definitions define the same function foo
with external linkage. And you are not allowed to provide more than one definition of any external linkage function in your entire program
6.9 External definitions
5 [...] If an identifier declared with external linkage is used in an expression (other than as part of the operand of asizeof
or_Alignof
operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.
In C++ the concept of linkage is extended: it assigns specific linkage to a much wider variety of entities, including types. In C++ class types have linkage. Classes declared in namespace scope have external linkage. And One Definition Rule of C++ explicitly states that if a class with external linkage has several definitions (across different translation units) it shall be defined equivalently in all of these translation units (http://eel.is/c++draft/basic.def.odr#12). So, in C++ your struct
definitions would be illegal.
Your function definitions remain illegal in C++ as well because of C++ ODR rule (but essentially for the same reasons as in C).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With