Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struct vs. Function Definitions in Scope

Tags:

c++

c

linkage

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++?

like image 777
V0ldek Avatar asked May 29 '18 18:05

V0ldek


People also ask

What is the scope of a struct?

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.

Can you define a function inside a struct?

No, you can't. Structs can only contain variables inside, storing function pointers inside the struct can give you the desired result.

Can I define function in struct C++?

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.

Is Dictionary same as struct?

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.


2 Answers

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.

like image 179
R Sahu Avatar answered Sep 21 '22 02:09

R Sahu


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 specifier extern.

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 a sizeof 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).

like image 29
AnT Avatar answered Sep 20 '22 02:09

AnT