我有以下代码片段,其中包含3个结构的全局指针:
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 文件编译它们时(其中我包含 structs.h 并使用 num_tail , num_head < / em>和 stack_head ),编译器( clang版本3.8.0 和 gcc 5.4.0 )编译此代码时没有错误,程序工作正常正如它应该。但是,就我而言,由于 structs.h 中缺少extern
修饰符,此代码不应正常编译并正常工作。它为什么有效? :)
UPD:是的,答案是暂定定义。实际上,在初始化指向NULL
的指针之后,编译器会给出错误消息。感谢所有的回复!
答案 0 :(得分:4)
暂定定义。您没有为这些全局变量赋值,因此它们被视为暂定定义。假设右侧={0};
,但只是暂时的。如果没有真正的定义,临时定义将合并。如果有的话,它会在不产生链接器冲突的情况下赢得暂定的那些。这通常通过常见符号(在C
输出中标记为nm
)来实现,这意味着即使在多个翻译单元中,您也可以对同一符号进行暂定定义。 (我认为最好不要依赖这个功能,坚持使用外部声明和非限定性定义。)
答案 1 :(得分:1)
默认情况下,不需要extern
,因为非静态变量已经具有外部范围。
事实上globals.c
中的声明是多余的。
Bignum *num_tail;
Bignum *num_head;
Stack *stack_head;
编译器仅针对重新定义的情况提供错误,例如,如果标头和来源中的num_tail
都已初始化。