【发布时间】:2021-09-07 22:58:13
【问题描述】:
我有这些由 3 个文件组成的虚拟软件:
测试.h
int gv;
void set(int v);
test.c
#include "test.h"
void set(int x) {
gv = x;
}
main.c
#include "test.h"
#include <assert.h>
int main() {
set(1);
assert(gv == 1);
}
代码在 MSVC 2019 和 GCC 8 中都能正常编译和运行,但在链接时使用 clang(Visual Studio 2019 提供的 clang-cl 11)失败,抱怨 gv 已定义:
1>------ Build started: Project: test, Configuration: Debug x64 ------
1>lld-link : error : undefined symbol: gv
1>>>> referenced by ...\test\main.c:6
1>>>> x64\Debug\main.obj:(main)
1>>>> referenced by ...\test\test.c:4
1>>>> x64\Debug\test.obj:(set)
1>Done building project "test.vcxproj" -- FAILED.
我知道extern 是在文件范围内定义的对象的默认storage-class specifier,但是如果我将extern 明确指定为int gv,它会破坏与每个编译器的链接(除非我为@ 添加定义987654331@ 当然是在源文件中)。
有些东西我不明白。发生了什么?
【问题讨论】:
-
omplaining about gv already define请发布确切的完整编译器错误消息,包括所有通知、行号和文件名。请发布您正在使用的编译器选项和编译器版本。你想研究常见的符号,比如stackoverflow.com/a/15604964/9072753。 -
编译器对
gv范围界定的方式不同。 (即它在文件中的可见性。)如果您将gv声明为extern,即extern int gv;。然后在main()中定义gv,即int gv = 0;,那么它在两个编译器中的工作方式可能相同。 -
根据@KamilCuk链接,这似乎只是一个UB案例,由于一些编译器扩展,它在某些平台上有效。
标签: c linker storage-class-specifier