首页 > 试题广场 >

为什么标准头文件都有类似以下的结构?

[问答题]
为什么标准头文件都有类似以下的结构?
#ifndef __INCvxWorksh 
#define __INCvxWorksh  
#ifdef __cplusplus 
extern "C" { 
#endif  
/*...*/  
#ifdef __cplusplus 
} 
#endif  
#endif /* __INCvxWorksh */ 
#ifndef __INCvxWorksh
#define __INCvxWorksh
#endif 

这一段是用来防止头文件重复包含,vs可以使用#pragma once。但是推荐使用宏定义来防止重复包含,其跨平台,兼容性好。

#ifdef _cplusplus  //这句表示如果是c++文件
extern "c" {           //用extern "c"把一段代码包起来
#endif
#ifdef _cplusplus
}
#endif
extern "c"的目的是告诉编译器以C语言的形式编译代码中的函数名,其目的是为了兼容C代码,常出现在动态链接库的代码中。
因为C++中有重载函数,为了区别相同函数名的重载函数,会在编译的时候在函数名后面加一串东西,来区别。而C语言中则没有重载,其编译时不会在函数名后加一串东西。
编辑于 2017-07-30 17:15:06 回复(0)
是C++中可以调用C的函数吧,说反了。 加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。
发表于 2018-06-26 20:55:52 回复(0)
1.这些都是预编译命令
解释extern "C"
2.cpp文件编译器会自己定义__cplusplus宏
3extern "c"有两个作用
1表示函数或变量时extern的,可以在本模块和其他模块使用
2为了在C++代码中使用c代码,有此声明后编译器会按照C的编译规则来编译那些代码
原因:c++支持重载,所以在编译成汇编时,真实函数名会带上函数的参数,而c不支持重载使用原函数名。这样就找不大在别的模块中使用c规则编译的此函数的代码,这时就会报连接错误
编辑于 2017-05-05 09:05:37 回复(0)
最后那句是不是有问题?“这样C语言就可以调用C++函数了”是不是得改成“这样C++就可以调用C语言函数了”?
发表于 2020-02-18 14:17:36 回复(1)
选择性编译
发表于 2016-03-08 20:21:18 回复(0)
管理宏定义
预处理就是在进行编译的第一遍词法扫描和语法分析之前所作的工作。说白了,就是对源文件进行编译前,先对预处理部分进行处理,然后对处理后的代码进行编译。这样做的好处是,经过处理后的代码,将会变的很精短。
 关于预处理命令中的文件包含(#include),宏定义(#define),书上已经有了详细的说明,在这里就不详述了。这里主要是对条件编译(#ifdef,#else,#endif,#if等)进行说明。以下分3种情况:
1:情况1:
#ifdef _XXXX
...程序段1...
#else
...程序段2...
#endif
 这表明如果标识符_XXXX已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。
例: 
#define NUM
.............
.............
.............
#ifdef NUM
 printf("之前NUM有过定义啦!:) \n");
#else
 printf("之前NUM没有过定义!:( \n");
#endif
}
 如果程序开头有#define NUM这行,即NUM有定义,碰到下面#ifdef NUM的时候,当然执行第一个printf。否则第二个printf将被执行。
 我认为,用这种,可以很方便的开启/关闭整个程序的某项特定功能。
2:情况2: 
#ifndef _XXXX 
...程序段1... 
#else 
...程序段2... 
#endif
 这里使用了#ifndef,表示的是if not def。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。例子就不举了。
3:情况3:
#if 常量 
...程序段1...
#else
...程序段2...
#endif 
 这里表示,如果常量为真(非0,随便什么数字,只要不是0),就执行程序段1,否则执行程序段2。
 我认为,这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1就好了。而不要测试的时候,只要将常量变0。
发表于 2017-02-23 20:59:41 回复(0)
头文件中的编译宏  
#ifndef __INCvxWorksh 
#define __INCvxWorksh 
#endif  
的作用是防止被重复引用。  
作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在symbol库中的名字与C语言的不同。例如,假设某个函数的原型为:   
void foo(int x, int y);  
该函数被C编译器编译后在symbol库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息,C++就是考这种机制来实现函数重载的。  
为了实现C和C++的混合编程,C++提供了C连接交换指定符号extern "C"来解决名字匹配问题,函数声明前加上extern "C"后,则编译器就会按照C语言的方式将该函数编译为_foo,这样C语言中就可以调用C++的函数了。
发表于 2015-10-28 18:03:24 回复(4)

避免一个头文件被多次引用

发表于 2020-03-26 09:55:39 回复(0)
加了extern c之后,c++如何实现重载
发表于 2020-03-13 09:54:28 回复(0)
 #ifdef与#endif的作用及用法
发表于 2019-07-16 16:49:57 回复(0)
#ifndef __INCvxWorksh #define __INCvxWorksh  #ifdef __cplusplus extern "C" { #endif  /*...这里是需要安c标准编译的代码*/  #ifdef __cplusplus } #endif  #endif  /* __INCvxWorksh */ 用来作为一种代码的选择性编译, 1选择编译哪部分代码; 2选择用什么标准编译; 可以用 #program once 只编译一次。
发表于 2018-09-13 16:23:24 回复(0)
#ifndef __INCvxWorksh
#define __INCvxWorksh 
防止重复调用

#ifdef _cplusplus  
extern"c"{         
#endif
#ifdef _cplusplus
}
#endif
如果是C++文件,以C的方式编译,并执行{}内的指令
发表于 2017-10-12 12:43:51 回复(0)
1.其中
#ifndef __INCvxWorksh
#define __INCvxWorksh
#endif 
防止函数被重复引用,因为c++是支持函数重载的,然而c不支持
#endif是就近原则
2.比如说一个函数 int sec(int a ,int b);c++中编译器会编译产生类似于_sec_int_int类型的函数,c++
就是靠这种方式重载的,然而c语言编译器会产生类型与_sec的函数,当加入extern ‘c’的时候就说明在c/c++
混合编程时候,编译器会按照c语言的风格编译,就不会产生函数重复引用的情况
发表于 2017-07-14 11:30:32 回复(0)
预编译宏定义是为了防止被重复引用。extern “C”学习了。原来C++实现函数重载的原理是这样的,编译产生的symbol中的名字带有函数名和参数数量及参数名。
发表于 2017-05-15 17:34:20 回复(0)
发表于 2016-09-26 11:33:08 回复(0)
防止被重复引用
发表于 2015-11-24 16:22:15 回复(0)