一般情况下,不应该将其移动以包含头文件。
extern "C"
用于指示函数使用C调用约定。声明对变量和#define
没有影响,因此不需要包含它们。如果#include
在extern "C"
块内部,则这实际上修改了该头文件内部的函数声明!
背景:如果没有extern "C"
声明,则在使用C编译器进行编译时,假定函数遵循C约定,在使用C++编译器进行编译时,则假定遵循C++约定。如果相同的头文件用于C和C++代码,则会出现链接器错误,因为编译的函数在C和C++中具有不同的名称。
虽然可以将所有代码放在#ifdef块之间,但我个人不喜欢这样做,因为它实际上只适用于函数原型,并且我经常看到人们将其复制粘贴到不应该的位置。最清晰的方法是将其保留在C / C ++头文件中的函数原型周围。
所以,回答你的问题“我应该将extern"C"
位移到包含头文件指令之前吗?”,我的答案是:不,你不应该。
但是,这是可能的吗?是的,在许多情况下,这不会破坏任何东西。有时它甚至是必要的,如果外部头文件中的函数原型不正确(例如,当它们是C函数并且您想从C ++调用它们),并且您无法更改该库。
然而,也有一些情况下这样做会破坏构建。以下是一个简单的示例,如果使用extern "C"
包装include,则编译失败:
foo.h:
#pragma once
#include "bar.h"
bar_status_t foo(void);
foo.c:
#include <stdio.h>
#include "foo.h"
#include "bar.h"
bar_status_t foo(void)
{
printf("In foo. Calling bar wrapper.\n");
return bar_wrapper();
}
bar.h:
#pragma once
typedef enum {
BAR_OK,
BAR_GENERIC_ERROR,
BAR_OUT_OF_BEAR,
} bar_status_t;
extern "C" bar_status_t bar_wrapper(void);
bar_status_t bar(void);
bar.cpp:
#include <iostream>
#include "bar.h"
extern "C" bar_status_t bar_wrapper(void)
{
std::cout << "In C/C++ wrapper." << std::endl;
return bar();
}
bar_status_t bar(void)
{
std::cout << "In bar. One bear please." << std::endl;
return BAR_OK;
}
main.cpp:
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
#include "bar.h"
int main(void)
{
bar_status_t status1 = foo();
bar_status_t status2 = bar();
return (status1 != BAR_OK) || ((status2 != BAR_OK));
}
当我在中取消注释这些块时,我遇到了以下错误:
main2.cpp:(.text+0x18): undefined reference to `bar'
collect2.exe: error: ld returned 1 exit status
Makefile:7: recipe for target 'app2' failed
如果没有这个问题,它可以顺利构建。一个C主函数只调用来自foo和bar的C函数,无论哪种方式都可以顺利构建,因为它不受#ifdef __cplusplus
块的影响。
__cplusplus
来移除模板声明,如果您像希望的那样将它们包装起来,您的头文件将基本上无法使用。因此,如已经提到的那样,确保您的声明正确,并让其他头文件自由地进行它们的操作。即使是标准库头文件也可能会出现问题(因为实现者可能会认为它们将被共享,然后在内部执行一些专家友好的操作)。 - StoryTeller - Unslander Monica