2016-12-22 20 views
4

我有以下代码片段用3个全局指针结构:一些神秘与 '的extern' 指向struct用C

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; 

当我编译这些与其他.C文件(wher e口包括structs.h和工作与num_tailnum_headstack_head),编译器(两者铛版本3.8.0GCC 5.4.0)通过编译程序和工程验证码正如它应该。但是,就我而言,此代码不应该正常编译和工作,因为缺少extern修饰符structs.h。它为什么有效? :)

UPD:是的,答案是暂定义。真的,在初始化指向NULL的指针之后,编译器会给出错误消息。感谢所有的答复!

+2

查找“暂定义C” – Peter

+0

尝试将头文件包含到2个不同的'.c'文件中,看看发生了什么.... – LPs

+0

这是一个[链接](https://github.com/Alkaizyr/Polish-calculator)存储与此程序。标题包含在所有.c文件中,一切正常。 –

回答

4

暂定义。您不会为这些全局变量赋值,因此将它们视为暂定义。假设右手边={0};,但只是暂时的。如果没有真正的定义,暂定义将被合并。如果有的话,它会赢得暂时的,而不会造成链接器冲突。这通常通过通用符号实现(在nm输出中标记为C),这意味着即使在多个翻译单元中,也可以对同一符号进行试探性定义。 (我认为最好不要依赖这个特性,并坚持extern声明加上无定义的定义。)

1

默认情况下,不需要extern,因为非静态变量已具有外部范围。

事实上,globals.c中的声明是多余的。

Bignum *num_tail; 
Bignum *num_head; 
Stack *stack_head; 

,编译器将给出错误只为重新定义的情况下,例如,如果在num_tail头和源是都初始化