首页 > 试题广场 >

extern "C"{}的作用以及能解决什么问题?

[不定项选择题]
extern "C"{}的作用以及能解决什么问题?
  • 在C++源文件中的语句前面加上extern "C",表明它按照类C的编译和连接规约来编译和连接,而不是C++的编译的连接规约
  • 主要是解决在C++代码中调用C代码
  • 主要是解决在C代码中调用C++代码
  • 上述描述都不正确
推荐
【正确答案】A B
【解析】extern "C" 的作用是为了能够正确的实现 C++ 代码调用 C 语言代码。加上 extern "C" 后,会指示编译器这部分代码按照 C 语言(而不是 C++)的方式进行编译。由于 C++ 支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译 C 语言代码的函数时不会带上函数的参数类型,一般只包括函数名。 这个功能十分有用处,因为在 C++ 出现以前,很多代码都是 C 语言写的,而且很底层的库也是 C 语言写的,为了更好的支持原来的 C 代码和已经写好的 C 语言库,需要在 C++ 中尽可能的支持 C,而 extern "C" 就是其中的一个策略。
 
extern "C"知识点讲解】
更多C++基础专业知识讲解,点击链接即可查看
https://www.nowcoder.com/link/zxyl-cpp33
编辑于 2021-11-17 15:40:50 回复(0)
AB
extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。
(1) 被extern "C"限定的函数或变量是extern类型的
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:
extern int a;
仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。
与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。
(2) 被extern "C"修饰的变量和函数是按照C语言方式编译和连接的
发表于 2015-01-05 23:20:03 回复(1)
AB
http://blog.csdn.net/daydreamingboy/article/details/8775409
发表于 2015-04-13 14:32:27 回复(0)

通过 g++ -S 1.cpp -o 1.S 导出汇编文件,其中 1.S 部分内容如下:
....
movq    %rsp, %rbp
.cfi_def_cfa_register 6
call    PrintA
call    _Z6PrintBv
call    _Z6PrintCv
movl    $0, %eax
popq    %rbp
....
可以看出PrintA的修饰与PrintB与PrintC不同。

通过 gcc -S 2.c -o 2.S 导出汇编文件,其中2.S 部分内容如下:
.string "PrintA"
.text
.globl  PrintA
.type PrintA, @function

通过 g++ -S 3.cpp -o 3.S 导出汇编文件,其中3.S 部分内容如下:
.string "PrintC"
.text
.globl  _Z6PrintCv
.type _Z6PrintCv, @function

通过命令进行编译,链接:
$ g++ -c 1.cpp -o 1.o
$ g++ -c 3.cpp -o 3.o
$ gcc -c 2.c -o 2.o
$ g++ 1.o 2.o 3.o -o a.out
执行 ./a.out 输出:
PrintA
PrintB
PrintC

可以看出gcc/g++处理.c文件和.cpp文件中,函数修饰名不同,使用 extern "C"{}后在链接过程中,1.cpp文件中的PrintA函数才可以正确连接到2.c中的PrintA文件(通过两个文件.S中的函数修饰名判断)。若不使用 extern "C"{},1.cpp中的PrintA编译后变为_Z6PrintAv,而2.c中的PrintA编译后为PrintA,两个函数名称不同,无法正确链接。

删除 extern "C"{} 保留 extern void PrintA(void); 语句后,执行
$ g++ -c 1.cpp -o 1.o
$ g++ 1.o 2.o 3.o -o a.out
1.o:在函数‘main’中:
1.cpp:(.text+0x27):对‘PrintA()’未定义的引用
collect2: 错误:ld 返回 1

可以通过 c++filt _Z6PrintBv 命令查看函数名
$ c++filt _Z6PrintBv
PrintB()
编辑于 2018-03-06 16:43:42 回复(0)
AB 被extern "C"修饰的变量和函数是按照C语言方式进行编译和链接的:这点很重要!!!!
发表于 2015-06-03 21:29:10 回复(0)
C如果要调用c++ 那么在定义的时候就要加上extern c
发表于 2020-08-23 11:05:52 回复(0)
???应该是AC,这道题有问题,C++完全包容C,根本不需要解决任何问题,而C调用C++才需要,答案应该是AC,是为了解决C调用C++
发表于 2020-08-01 18:36:09 回复(0)
B和C别搞混
C代码用C的规则来编译和连接,C++代码用C++的规则来编译和连接;
当C++代码中引用C代码时,C代码用C++的规则来编译和连接会出现问题,这时候引入extern "C"{ },被大括号括起来的部分用C的规则来编译和连接
发表于 2019-06-03 10:35:53 回复(0)
extern "C"修饰的变量和函数是按照C语言方式进行编译和链接的:这点很重要
发表于 2016-09-21 20:50:26 回复(0)
被extern "C"修饰的变量和函数是按照C语言方式进行编译和链接的
发表于 2016-03-26 12:09:44 回复(0)