这里我有一个小程序:

// header.h
#pragma once
int a;
int reta();

// extra.c
#include "header.h"
int reta() {
    return a;
}

// main.c
#include "header.h"
#include <stdio.h>
int main(void) {
    printf("%d, %d", a, reta());
}

使用Visual Studio编译时的结果(C标准:c17,x64):

0,0

使用GCC编译时的结果(gcc—L.—o test.exe *. c—std = c17—mwindows—Wl,—subsystem,console):

C:/msys64/ucrt64/bin/../ lib/gcc/x86_64—w64—mingw32/13.2.0/../../ x86_64—w64—mingw32/bin/ld. exe:C:...\ Temp\ccGvFOtk. o:main. c:(.+0x0):`a '的多重定义;C:...\ Temp\ccANU1lv.o:extra. c:(.+0x0):首先在此定义 collect2.exe:error:ld returned 1 exit status

问题是: 为什么会有差异?我应该做些什么来修复GCC case 中的错误?

推荐答案

在头文件中,你有一个tentative definition/a. 这意味着你的两个. c文件包含这个头文件的定义都是a. 定义tentative是因为它没有显式初始化.

有些编译器,如本例中的MSVC,会将多个暂定定义合并为一个定义. 然而,您使用的gcc版本却没有,这就是为什么您会得到多重定义错误的原因. 如果您在头文件中初始化了a,它将是一个完整的定义,并且两个编译器都可能给出错误.

处理这个问题的正确方法是在头文件中使用declarea,而在一个源文件中使用define.

// header.h
#pragma once
extern int a;        // declaration of a
int reta();

// extra.c
#include "header.h"

int a;               // definition of a

int reta() {
    return a;
}

// main.c
#include "header.h"
#include <stdio.h>
int main(void) {
    printf("%d, %d", a, reta());
}

C++相关问答推荐

%p与char* 等组合缺少的GCC Wform警告

如何启用ss(另一个调查套接字的实用程序)来查看Linux主机上加入的多播组IP地址?

ATmega328P USART发送字符重复打印

从内联程序集调用Rust函数和调用约定

C/SDL程序,渲染不使用我的渲染器

我应该如何解决我自己为iOS编译的xmlsec1库的问题?转换Ctx.first在xmlSecTransformCtxPrepare()之后为空

如何在不使用其他数组或字符串的情况下交换字符串中的两个单词?

C在声明带有值的数组时,声明大小有用吗?

如何计算打印二叉搜索树时每行所需的空间?

cairo 剪辑区域是否存在多个矩形?

如何用C语言为CLI应用程序编写按键检测系统?

在vfork()之后,链接器如何在不 destruct 父内存的情况下解析execve()?

将多项式从文件.txt加载到终端时出现问题

CS50 pset 5的皱眉脸正确地处理了大多数基本单词,并且拼写判断不区分大小写.

程序如何解释变量中的值

在C中使用字符串时是否不需要内存分配?

保存有符号整数结果的变量是否会溢出(后增量的副作用),并且此后从未在任何表达式中使用过它,是否会导致 UB?

无法在线程内用 C 打印?

OpenGL 中的非渐变 colored颜色 变化

为什么使用 C 引用这个 char 数组会导致 Stack smasing?