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