cpp之宏和函数调用约定
宏定义
宏中的#和##
首先知道理解c中的邻近字符串连接原则,即相邻两个字符串链接起来组成一个字符串。
printf("L" "java/lang/Object;""\n");
是合法的并且输出结果是Ljava/lang/Object;
#define LOG(NAME, VALUE) log_info("the value of " #NAME " is :", VALUE)
#NAME会把传入的参数名当成字符串处理
##将##
两边的字符连在一起作为一个标识符
#define VAR_N(name,n) name##n
VAR_N(age,1) -> age1
宏的副作用
问题
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
如果代入++
--
类型的参数会导致++
--
被多次执行产生副作用。比如:
int i=0; int j=10;
int c = MIN(i++,j++);
会被展开为 ((i++) <= (j++) ? (i++) : (j++))
最终导致返回的结果: i=2,j=11,c=1 从而产生副作用(i++执行了两次,并且结果不正确本应为0)。
解决
使用语句表达式消除副作用
#define min(x, y) ({ const typeof(x) _x = (x); \
const typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; \
})
方法名修饰(Decorated Name)规则和函数调用约定
C编译器的函数名修饰规则
-
__stdcall调用约定:
编译器和链接器会在输出函数名前加上一个下划线前缀,函数名后面加上一个“@”符号和其参数的字节数,例如_functionname@number。
-
__cdecl调用约定:
仅在输出函数名前加上一个下划线前缀,例如_functionname。
-
__fastcall调用约定:
在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数,例如@functionname@number 。
C++编译器的函数名修饰规则
cpp与c交叉调用
cpp调用c:头文件如下声明,cpp文件引用头文件。
#ifdef __cplusplus
extern "C" {
#endif
void show(PERSON* person);
#ifdef __cplusplus
}
#endif
c调用cpp: 头文件按照上面的方式,cpp实现中引用头文件,c调用文件中添加extern void show(PERSON* person);
申明。