c++ - 项目中同一头文件的多个包含:C vs C++
问题描述
这里我有一个示例项目,有两个源文件和一个头文件,如下:
主.c:
#include<stdio.h>
#include "personal.h"
int main(){
i = 5;
printf("Value is %d\n",i);
return 0;
}
子c:
#include "personal.h"
// do nothing
最后是personal.h:
#pragma once
int i;
每个.c 文件都包含personal.h,它是“受保护的”。我用 gcc 编译,一切正常:
>gcc sub.c main.c -o out
>./out
Value is 5
但是使用 g++,会发生这种情况:
>g++ sub.c main.c -o out
/tmp/cctYwVnO.o:(.bss+0x0): multiple definition of `i'
/tmp/ccPElZ27.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
在文件链接方式、预处理器活动等方面,C++ 和 C 之间有什么根本不同吗?我对像 clang 这样的其他编译器进行了同样的尝试,并且发生了同样的情况。我可能在这里遗漏了一些愚蠢的东西。
解决方案
在 C 中,
int i;
是一个暂定的定义。借助包含,您可以i
在两个编译单元中获得暂定定义。C 标准允许在多个编译单元中具有暂定定义,但不强制实现接受这一点。-fno-common
Unix C 编译器的自定义行为是允许它,但 gcc 有一个选项(或者对于允许更好代码的平台——我不知道,但这是 GCC 文档给出的基本原理)。
IIRC,C++ 没有这样的津贴。
请注意,您可能需要声明而不是标题中的定义。因此,对于i
上述情况,它应该是
extern int i;
在标题和一个
int i;
在一个 .c
文件中的全局范围内。
推荐阅读
- javascript - 如何在两个不同的相同网页上显示选定的选项?
- asp.net-mvc - 当用户没有权限时如何重定向到特殊页面?
- firebase - Cloud Functions 的 Firebase 模拟器未更新代码
- bash - 如何使用 bash 从文本文件创建词汇表?
- docker - 使用手动 docker build 在 Heroku 上托管 API
- docker - Ontotext GraphDB on Docker - 如何使用主机文件系统上的文件而不是容器内的文件
- python - 无法使用 GTTS 播放和将 .txt 转换为 mp3
- javascript - 是否可以为类创建动态属性?
- asp.net - Swagger UI 不会在我的控制器的 GET 操作中为我的复杂类型参数呈现主体参数字段
- c - 箭头运算符和后增量的优先级?