C/C++语言补缺 宏- extern "C"-C/C++互调
1. 宏中的#
宏中的#的功能是将其后面的宏参数进行字符串化操作(Stringizing operator),简单说就是在它引用的宏变量的左右各加上一个双引号。
如定义好#define STRING(x) #x之后,下面二条语句就等价。
char *pChar = "hello"; == char *pChar = STRING(hello);
还有一个#@是加单引号(Charizing Operator)
#define makechar(x) #@x; == char ch = makechar(b);与char ch = 'b';等价。
注意,宏中遇到#或##时就不会再展开宏中嵌套的宏了。
比如使用char *pChar =STRING(__FILE__);虽然__FILE__本身也是一个宏,但编译器不会展开它,所以pChar将指向"__FILE__"。
因此要加一个中间转换宏,先将__FILE__解析成你希望的字符串。
#define _STRING(x) #x
#define STRING(x) _STRING(x)
再调用下面语句将输出带""的源文件路径
char* pChar = STRING(__FILE__);
printf("%s %s\n", pChar, __FILE__);
2. 宏中的##
##的功能:拼接符号(Token-pasting operator)。
eg. #define paster( n ) printf( "token"#n" = %d\n", token##n )
int token9 = 100;
再调用 paster(9);宏展开后token##n直接合并变成了token9。整个语句变成了 printf( "token""9"" = %d", token9 );
在C语言中字符串中的二个相连的双引号会被自动忽略,于是上句等同于 printf("token9 = %d", token9);。
即输出token9 = 100.
3. extern "C"
extern "C"的真实目的是实现类C和C++的混合编程。在C++源文件中的语句前面加上extern "C",表明它按照类C的编译和连接规约来编译和连接,而不是C++的编译的连接规约,但仍然要遵守C++的类型检测、参数转换规则。这样在类C的代码中就可以调用C++的函数/变量等。(注:类C,代表的是跟C语言的编译和连接方式一致的所有语言)
4. C++中调用C的代码
假设一个C的头文件cHeader.h中包含一个函数print(int i),为了在C++中能够调用它,必须要加上extern关键字(原因在extern关键字那节已经介绍)。它的代码如下:
|
1
2
3
4
5
6
|
#ifndef C_HEADER#define C_HEADERextern void print(int i);#endif C_HEADER |
相对应的实现文件为cHeader.c的代码为:
|
1
2
3
4
5
6
|
#include <stdio.h>#include "cHeader.h"void print(int i){ printf("cHeader %d\n",i);} |
现在C++的代码文件C++.cpp中引用C中的print(int i)函数:
|
1
2
3
4
5
6
7
8
9
|
extern "C"{#include "cHeader.h"}int main(int argc,char** argv){ print(3); return 0;} |
5. C中调用C++的代码
现在换成在C中调用C++的代码,这与在C++中调用C的代码有所不同。如下在cppHeader.h头文件中定义了下面的代码:
|
1
2
3
4
5
6
|
#ifndef CPP_HEADER#define CPP_HEADERextern "C" void print(int i);#endif CPP_HEADER |
相应的实现文件cppHeader.cpp文件中代码如下:
|
1
2
3
4
5
6
7
8
|
#include "cppHeader.h"#include <iostream>using namespace std;void print(int i){ cout<<"cppHeader "<<i<<endl;} |
在C的代码文件c.c中调用print函数:
|
1
2
3
4
5
6
|
extern void print(int i);int main(int argc,char** argv){ print(3); return 0;} |
注意在C的代码文件中直接#include "cppHeader.h"头文件,编译出错。而且如果不加extern int print(int i)编译也会出错
C/C++语言补缺 宏- extern "C"-C/C++互调的更多相关文章
- c 语言中宏定义和定义全局变量的区别
宏定义和定义全局变量的区别: 1 作用时间不同. 宏定义在编译期间即会使用并替换,而全局变量要到运行时才可以. 2 本质类型不同. 宏定义的只是一段字符,在编译的时候被替换到引用的位置.在运行中是没有 ...
- C语言中宏定义(#define)时do{}while(0)的价值(转)
C语言中宏定义(#define)时do{}while(0)的价值 最近在新公司的代码中发现到处用到do{...}while(0),google了一下,发现Stack Overflow上早有很多讨论,总 ...
- 注解是建立在class文件基础上的东西,同C语言的宏有异曲同工的效果
注解是建立在class文件基础上的东西,同C语言的宏有异曲同工的效果 https://www.cnblogs.com/deman/p/5519901.html @是java注解,即annotation ...
- C语言的宏macro的使用
C's Macro Introduction 1.The Connect Macros: ## 这是一个预处理连接符,这个操作符主要用来将两个符号连接成为一个完整的宏符号.通过下面的代码,可以看到其具 ...
- C语言基础--宏
宏在C语言中经常使用,在linux的源码中可以看到很多宏的高级应用.因此不理解宏,就很难理解代码.本文参考一些互联网资料做一些总结,希望给大家带来帮助. 先说说使用宏的优点及缺点: 优点: 1.提高代 ...
- C语言高级宏技巧
特殊符号#.## (1)# When you put a # before an argument in a preprocessor macro, the preprocessor turns t ...
- C语言之宏
所谓的宏就是一种预处理命令,什么是与处理呢?即在编译过程之前先对程序代码做出的必要的转换处理.宏有两个作用: 1.当遇到需要将程序某个特定的数量在程序中出现的所有实例通通加以修改时,程序只需改动一处即 ...
- 【编程基础】C语言常见宏定义
我们在使用C语言编写程序的时候,常常会使用到宏定义以及宏编译指令,有的可能比较常用,有的可能并不是很常用,是不是所有的C语言宏定义以及宏指令你都清楚呢? 指令 用途详细介绍 # 空指令,无任何效果 # ...
- C语言在宏定义中使用语句表达式和预处理器运算符
语句表达式的亮点在于定义复杂功能的宏.使用语句表达式来定义宏,不仅可以实现复杂的功能,而且还能避免宏定义带来的歧义和漏洞.下面以一个简单的最小值的宏为例子一步步说明. 1.灰常简单的么,使用条件运算符 ...
随机推荐
- 从零开始安装 Ambari (1) -- 安装前的准备工作
Ambari 没有简单的 .tar.gz 结尾的包(反正我找到).apache 官网提供的安装方法,是要下载源码,自己编译成安装包安装.说明文档还不够细.编译的时候是用 maven,照理来说不应该会失 ...
- 洛谷P1083 借教室
P1083 借教室 题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借 ...
- angularJs解决模态框下echarts不显示问题
例如:摸态框myModal.html,给它命名一个id,id='myModal'; myModal.html页面想画一个echarts图表 这里是angularJs已经封装好的echarts在html ...
- springboot2.0+Neo4j+d3.js构建知识图谱
Welcome to the Neo4j wiki! 初衷这是一个知识图谱构建工具,最开始是对产品和领导为了做ppt临时要求配合做图谱展示的不厌其烦,做着做着就抽出一个目前看着还算通用的小工具 技术栈 ...
- 自增长 auto_increment
auto_increment :自动编号,一般与主键组合使用.一个表里面只有一个自增默认情况下,起始值为1,每次的增量为1. 例子:create table tb5( id int primar ...
- BZOJ 2462 [BeiJing2011]矩阵模板 矩阵哈希
昨天卡了一天常数...然后发现吧$unsigned\space long\space long$改成$unsigned$就可以过了$qwq$ 先把每一行的前缀哈希求出,然后再竖着把每个前缀哈希值哈希起 ...
- 长春理工大学第十四届程序设计竞赛(重现赛)M.Orx Zone
链接:https://ac.nowcoder.com/acm/contest/912/M 题意: Daenerys Stormborn, 风暴中出生的丹尼莉丝,the Unburnt, 烧不死的,Qu ...
- spark_spark连接hive config
1 环境 hadoop2.7.3 apache-hive-2.1.1-bin spark-2.1.0-bin-hadoop2.6 jdk1.8 2 配置文件 在hive-site.xml中配置mysq ...
- HQL和SQL
hql是面向对象查询,格式:from + 类名 + 类对象 + where + 对象的属性 sql是面向数据库表查询,格式:from + 表名 + where + 表中字段 1.查询 一般在hiber ...
- 浅谈ThreadLocal模式
一.前言: ThreadLocal模式,严格意义上不是一种设计模式,而是java中解决多线程数据共享问题的一个方案.ThreadLocal类是java JDK中提供的一个类,用来解决线程安全问题,并不 ...