C++学习之#define

C++学习之#define

文章目录

  • C++学习之#define
    • 1. #define是什么
    • 2. #define用法
      • 1)#define定义标识符
      • 2)#define定义函数
      • 3)宏定义中的特殊操作符
        • `#`的用法
        • `##`的用法
        • `@#`的用法
        • `/`的用法
        • 可变参数宏`...`和`__VA_ARGS__`

1. #define是什么

C语言中,#表示其为预处理命令,define为宏定义命令。

可以用#define定义一个标识符来表示一个常量。其特点是:定义的标识符不占内存,只是一个临时的符号,预编译后的这个符号就不存在了。

#define又称宏定义,标识符为所定义的宏名,简称宏。宏名表示的是一个常量,可以给变量赋值。

宏定义最大的好处是方便程序的修改,使用宏定义可以用宏代替一个在程序中经常使用的常量。且当常量比较长时,使用宏就可以用较短的标识符来代替,这样编程更方便不易出错。宏定义的优点是方便和易于维护

在预编译时,会将程序中所有出现标识符的地方用这个常量替换,称为宏替换宏展开,预编译所执行的操作就是简单的文本替换。预编译指令不是语句,所以后面不能加分号。

2. #define用法

#define定义标识符一般形式为:

#define  标识符  常量   //注意, 最后没有分号

宏所表示的常量可以是数字、字符、字符串、表达式,其中最常用的是数字。

#define作用域为自#define那一行起到源程序结束。如果要终止其作用域可以使用#undef命令。

1)#define定义标识符

#define PI 3.14159
#define NAME Kitty
int main(void)
{
    double r = 1;//圆半径
    double s = PI * r * r;//圆面积 //这里将PI替换为3.14159
    printf("s = %f\n", s);
    
    printf("my name is %s", NAME);
    return 0;
}

2)#define定义函数

#define FUNCA(a, b) a+b
#define FUNCB(a, b) (a+b)

template
T func(T a, T b)
{
    return(a + b);
}

int main(void)
{
    int a = 1;
    int b = 2;
    printf("a * FUNCA(a, b) * b = %d", a*FUNCA(a, b)*b);
    printf("a * FUNCB(a, b) * b = %d", a*FUNCB(a, b)*b);
    printf("a * func(a, b) * b = %d", a*func(a, b)*b);
    return 0;
}

//结果 //仅文本替换,可以看出有无括号的区别
a * FUNCA(a, b) * b = 5 //= a*a+b*b
a * FUNCB(a, b) * b = 6 //= a*(a+b)*b
a * func(a, b) * b = 6 //函数调用

3)宏定义中的特殊操作符

#的用法

宏定义中的#是字符串化操作符。其作用是:将宏定义中的传入参数名转换成一对用双引号括起来的参数名字符串。其只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。

#define STR(str) #str

int a = 123;
STR(a); //这里的宏会扩展为"a"

#define PRINT(x) printf("the square of " #x " is %d.\n", (x)*(x))
PRINT(2);//the square of 2 is 4.
PRINT(2+1);//the square of 2+1 is 9.

对空格的处理

  1. 当传入单个参数名,忽略传入参数名前面和后面的空格;

    STR( a ) 会被扩展为 “a”

  2. 当传入的多个参数名之间存在空格时,编译器会自动连接各个子字符串,中间只保留一个空格,忽略其余空格。

    STR( a b ) 会被扩展为 “a b”

##的用法

##是连接符号,把参数连接在一起。

#define CAT(X, Y) X##Y

int XY = 2023;
printf("%d\n", CAT(X, Y)); //这里CAT(X, Y)把X和Y连接在一起,变为XY,XY需要提前声明,否则会找不到XY而产生未定义的错误

#define paster( n ) printf( "token" #n " = %d\n", token##n )

int token9 = 9;
paster(9); //token9 = 9
@#的用法

字符化操作符,只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。作用是将传的单字符参数名转换成字符,以一对单引用括起来。

#define makechar(x) @#x
a = makechar(b); //a = 'b'
/的用法

当定义的宏不能用一行表达完整时,可以用"/"表示下一行继续此宏的定义。

可变参数宏...__VA_ARGS__

VA_ARGS是一个可变参数的宏

实现思想就是宏定义中参数列表的最后一个参数为省略号,这样预定义宏__VA_ARGS__就可以被用在替换部分,替换省略号所代表的字符串。

#define PR(...) printf(__VA_ARGS__)

PR("hello\n");

int a = 1, b = 2;
PR("a = %d, b = %d", a, b);

几个系统的宏

  • __FILE__宏在预编译时会替换成当前的源文件名
  • __LINE__宏在预编译时会替换成当前行号
  • __FUNCTION__宏在预编译时会替换成当前的函数名称

a = 1, b = 2;
PR(“a = %d, b = %d”, a, b);

几个系统的宏

  • __FILE__宏在预编译时会替换成当前的源文件名
  • __LINE__宏在预编译时会替换成当前行号
  • __FUNCTION__宏在预编译时会替换成当前的函数名称

参考了一些文章:

  • define宏定义中的#,##,@#及/符号
  • C++之define详解
  • 深入了解#define

你可能感兴趣的:(C++,c++)