我最近发现了一些代码,其中extern“C”也被添加到源文件中以用于函数。 它们也被添加到声明它们的头文件中。
我假设在头文件中添加’extern“C”就足够了。
应该在哪里添加extern“C”块?
更新:假设我正在使用CPP编译器编译我的C代码,并为头文件中的所有函数添加了外部“C”防护(即我的所有函数都在头文件中有原型),但在源文件中我没有添加相同的。 这会导致问题吗?
既然你的意思
extern "C" { ... }
样式保护,这些声明一些函数是“C”链接,而不是“C ++”链接(它通常有一堆额外的名称装饰来支持像重载函数之类的东西)。
当然,目的是允许C ++代码与C代码接口,C代码通常在库中。 如果库的标题不是用C ++编写的, 那么它们就不会包含C ++的extern "C"
保护 。
用C ++编写的AC标题将包含一些内容
#ifdef __cplusplus extern "C" { #endif ... #ifdef __cplusplus } #endif
确保C ++程序看到正确的链接。 但是,并非所有库都是用C ++编写的,所以有时你必须这样做
extern "C" { #include "myclibrary.h" }
使连接正确。 如果头文件是由其他人提供的,那么改变它是不好的做法(因为那时你不能轻易更新它),所以最好用你自己的后卫(可能在你自己的头文件中)包装头文件。
extern "C"
不是(AFAIK)ANSI C,因此在没有预处理器保护的情况下不能包含在普通C代码中。
为了回应您的编辑:
如果您使用的是C ++编译器,并且在头文件中将函数声明为extern“C”,则无需在实现文件中将该函数声明为extern“C”。 从C ++标准的7.5节(强调我的):
如果同一函数或对象的两个声明指定了不同的链接规范(即,这些声明的链接规范指定了不同的字符串文字),如果声明出现在同一个转换单元中,则程序格式错误,并且如果声明出现在不同的翻译单元中,则适用一个定义规则。 除了具有C ++链接的函数之外,没有链接规范的函数声明不应位于该函数的第一个链接规范之前。 在看到明确的链接规范之后,可以在没有链接规范的情况下声明函数; 在早期声明中明确指定的链接不受此类函数声明的影响。
我不相信这是一个好的做法,因为链接规范可能会偶然发生分歧(例如,如果包含链接规范的头文件未包含在实现文件中)。 我认为最好在实现文件中明确。
他们只需要进入其他源文件包含的任何内容。
有了一些习语,你会找到包括源文件在内的人。
它们应该添加到所有文件中,并包含在其他文件中。
通常,一个不包含源文件。
你的意思是’extern c’预处理器? 它们必须在函数定义上,并且影响函数调用如何存储在已编译的二进制文件中。 如果你将编译的c ++与编译为C的c(与.cpp文件中的c相对)链接在一起,那么它才真正需要。
辩解书
这个问题已经变得更加清晰了。 这个答案解决了原始问题,当它至少是有争议的是它是否正在讨论防止多头包含在头文件中 – 这是我的答案所解决的。 显然,如果问题已经像现在一样清楚,我就不会提交这个答案。
原始答案
不,也没有必要在C代码中包含防护装置。
如果头文件’header.h’说:
#ifndef HEADER_H_INCLUDED #define HEADER_H_INCLUDED ... #endif
那么源文件’source.c’是完全安全的:
#include "header.h"
其他标题包含’header.h’也是安全的。
然而,人们注意到打开头文件并阅读它需要时间,这会减慢编译速度,因此有时人们会这样做:
#ifndef HEADER_H_INCLUDED #include "header.h" #endif
这意味着如果’source.c’中包含的其他标题已包含’header.h’,则不会重新处理’#include’。 (或者,如果’header.h’已经直接包含在’source.c’中,尽管这是一个愚蠢的小问题。)
因此,遇到这种情况时,很可能是尝试优化编译性能。 它很难买到它,这还不是很清楚; 现代C预处理器对这个问题非常聪明,如果可以的话,将避免重新包含文件。 而且’source.c’中的测试总是有一个错误(也许是#ifndef HEARER_H_INCLUDED),在这种情况下,测试会减慢编译速度,因为预处理器会测试不相关的条件,然后继续包含’header.h’。所有。 这是’安全’; 标题本身受到保护 – 或应该是。
如果您看到’source.c’中的代码也执行’#define HEADER_H_INCLUDED’,那么就会出现问题。 #define必须在#include之前或之后,并且都不是一般技术。
请注意,标题的正文出现在’#define HEADER_H_INCLUDED’之后。 如果嵌套包含’header.h’,则再次保护。
“C”卫兵有两个目的:
由于您在实现文件中也包含带有“C”保护的标头,因此编译器可以使用有关如何在编译时创建符号的信息,编译器将以可以由a使用的方式创建符号。非C ++编译器。 因此,只需在头文件中指定extern“C” ,只要头文件也包含在实现文件中。
如果在源文件中使用extern,则不需要它们,如果它们在头文件中使用,并且该文件包含在其余源文件中。
据我记得标准,默认情况下所有函数声明都被视为“extern”,因此不需要明确指定它。 这不会使这个关键字无用,因为它也可以与变量一起使用(在这种情况下 – 它是解决链接问题的唯一解决方案)。 但是有了这些function – 是的,它是可选的。
更冗长的答案是它允许您使用在另一个源代码文件中编译的变量,但不为变量保留内存。 因此,要利用extern,您必须拥有源代码文件或库单元,其中包含顶层变量的内存空间(不在函数内)。 现在,您可以通过在其他源代码文件中定义同名的extern变量来引用该变量。
通常,应避免使用外部定义。 它们很容易导致无法管理的代码和难以定位的错误。 当然,有些例子表明其他解决方案不切实际,但很少见。 例如,stdin和stdout是映射到stdin.h中类型为FILE *的extern数组变量的宏; 此arrays的内存空间位于标准C库单元中。
需要了解更多c/c++开发分享是否还需要在源文件中添加“extern C”?,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!
以上就是c/c++开发分享是否还需要在源文件中添加“extern C”?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/979920.html