I have the following pieces of code with 3 global pointers to structs:
structs.h:
#pragma once
typedef struct Bignum {
int digit;
struct Bignum *next;
struct Bignum *prev;
} Bignum;
typedef struct Stack {
struct Bignum *head;
struct Bignum *tail;
char sign;
struct Stack *next;
} Stack;
Bignum *num_tail;
Bignum *num_head;
Stack *stack_head;
globals.c:
#include "structs.h"
Bignum *num_tail;
Bignum *num_head;
Stack *stack_head;
When I compile these with other .c files (where I include structs.h and work with num_tail, num_head and stack_head), compilers (both clang version 3.8.0 and gcc 5.4.0) compile this code without errors and program works as it should. But, as far as I'm concerned, this code should not be normally compiled and work because of lack of extern
modifier in structs.h. Why does it work? :)
UPD: Yes, the answer is tentative definitions. Really, after initializing pointers to NULL
, compilers give an error message. Thanks for all the replies!
Tentative definitions. You don't assign a value to those globals so they're treated as tentative definitions. The right-hand side
={0};
is assumed but only tentatively. If there's no real definition, the tentative definitions will get merged. If there is one, it'll win over the tentative ones without creating a linker conflict. This is normally implemented via common symbols (markedC
innm
output), which means you can have tentative definitions for the same symbol even in multiple translation units. (I think it's best to not rely on this feature and stick to extern declarations coupled with nontentative definitions.)