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 ", pChar, __FILE__);
2. 宏中的##
##的功能:拼接符号(Token-pasting operator)。
eg. #define paster( n ) printf( "token"#n" = %d ", 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_HEADER extern 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
" ,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_HEADER extern "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)编译也会出错