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);申明。

posted on 2019-05-24 17:12  andyhe  阅读(391)  评论(0编辑  收藏  举报

导航