C++宏定义中#和##的用法

11 篇文章 0 订阅

前段时间很到了宏定义中的新知识:#与##,感觉打开了新天地的大门。
首先来介绍一下这两种功能:

#
#的用法是负责将其后面的东西转化为字符串,比如:

#define TO_STRING(str) #str

int main(){
    cout << TO_STRING(this is a string) << endl;
    return 0;
}


这段代码中,TO_STRING宏就会将括号中的内容转化为字符串,生成"this is a string",然后由cout输出。

##
##是连接符,将前后两个东西连接成一个词。比如:

#define IntVar(i) int_##i

int main(){
    int int_1 = 1, int_2 = 2;
    cout << IntVar(1) << ", " << IntVar(2) << endl;
    return 0;
}


这段代码中IntVar(1)就会将前面的int_与参数1连接起来,成为int_1,然后由cout输出int_1变量对应的值1。对于IntVar(2)同理。

最开始我一看,emmmmmm,高级啊!可以生成新的词汇!因为我最开始想做的是,如果有很多int变量,他们基本模式都一样,那我是不是可以用一个for循环来直接生成?比如:

#define create_int(i) int int_##i = i
#define print_int(i) cout << int_##i << endl

int main(){
    for(int i = 1; i <= 3; ++i) create_int(i);
    for(int i = 1; i <= 3; ++i) print_int(i);
}


这样。当然,我很快发现我想多了。我犯了一个很低级的错误。宏定义是在预编译的时候就进行了展开,i的值则是在运行时才确定下来的,想想也应该知道不可能达到我预想中的效果。这样做只会生成int_i变量,而不是int_1、int_2之类的。

那么##的正确打开方式是什么呢?其实它做的只是帮我们省去不变的部分,可变的部分仍然需要我们自己去完成。对于上面这个小小的示例用处可能不太明显,我们换一个:

#define TEST_CASE_1 "This is a super super super super long string for test to process"
#define TEST_CASE_2 "This is another super super super super long string for test to process"
#define TEST_CASE_3 "This is again another super super super super long string for test to process"

#define process_data(i) \
string temp = TEST_CASE_##i;\
do_something

int main(){
    process_data(1);
    process_data(2);
    process_data(3);
}


比如说如上代码,do_something可能有很多行,而你重复的部分又难以做成循环,因为变量由于某种原因难以做成数组。这个时候用到##就会很方便啦~

另外,##还可以用来省略前缀。比如:

#define func(ptr, type) _func(ptr, T_##type)

enum TYPE{
    T_INT,
    T_FLOAT,
    T_CHAR,
}
void _func(void* ptr, TYPE type){
    switch(type){
    case T_INT:
        cout << *((int*)ptr) << endl; break;
    case T_FLOAT:
        cout << *((float*)ptr) << endl; break;
    case T_CHAR:
        cout << *((char*)ptr) << endl; break;
    default:
        break;
    }
}
int main(){
    int x = 1, *ptr = &x;
    func(ptr, INT);
}


这样就可以省去前缀,看起来更方便。

当然还有更多的用法,我就不一一列举啦。

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C++ 宏定义和 C 语言宏定义类似,也是一种预处理指令,用于在编译之前将源代码的标识符替换为指定的文本。不过,在 C++ 宏定义还可以用于实现一些类似函数的和模板元编程等高级特性。 C++ 宏定义的基本语法和 C 语言类似,如下所示: ```c++ #define 体 ``` 其名是标识符,体可以是任意合法的 C++ 表达式、语句或代码块。例如: ```c++ #define PI 3.1415926 #define MAX(a, b) ((a) > (b) ? (a) : (b)) ``` 上面的宏定义,第一个将名 PI 定义为常量 3.1415926,第二个将名 MAX 定义为求两个数的最大值的函数式。在源代码,可以通过名来引用体,例如: ```c++ float r = 1.0; float area = PI * r * r; int max_num = MAX(3, 5); ``` 与 C 语言相比,C++ 宏定义还有一些高级特性,包括: 1. 可变参数:类似于 C 语言的可变参数函数,可以定义一个参数数量不定的,例如: ```c++ #define PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__) ``` 上面的宏定义可以用来输出带格式的文本,类似于 printf 函数。 2. 预定义C++ 有一些预定义的,可以用来表示编译器、操作系统、编译时间等信息,例如: ```c++ #ifdef __cplusplus // C++ 代码 #else // C 代码 #endif ``` 上面的宏定义可以用来区分 C++ 代码和 C 代码。 3. 高级C++ 宏定义还可以用来实现一些高级特性,比如模板元编程、泛型编程等。例如: ```c++ #define STATIC_ASSERT(condition) \ typedef char static_assertion_##__LINE__[(condition) ? 1 : -1] ``` 上面的宏定义可以用来实现静态断言,类似于 C++11 的 static_assert。 需要注意的是,宏定义的滥用会导致代码的可读性和可维护性变差,因此需要谨慎使用宏定义,尽量使用 C++11 的 constexpr、inline、template 等语言特性替代宏定义。此外,还需要注意宏定义的展开顺序和优先级,以避免出现错误或者副作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值