• cpp之宏和函数调用约定


    宏定义

    宏中的#和##

    首先知道理解c中的邻近字符串连接原则,即相邻两个字符串链接起来组成一个字符串。
    printf("L" "java/lang/Object;"" ");是合法的并且输出结果是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);申明。

  • 相关阅读:
    2016年3月17日----Javascript的正则表达式
    2016年3月17日----Javascript的时间与日期
    2016年3月9日----Javascript的对象和数组
    2016年3月8日----Javascript的函数
    2016年3月7日----Javascript的运算符
    2016年3月7日----Javascript的数据类型
    2016年3月1日----Javascript的数组元素的添加、移除以及其他常用方法
    console深入理解
    浏览器特性和安全策略
    每日新知
  • 原文地址:https://www.cnblogs.com/andyhe/p/10919201.html
Copyright © 2020-2023  润新知