0x01 宏的初识

C 语言中的宏(Macro),可以简单理解为:

在程序正式编译之前,由预处理器按照规则进行文本替换的东西。它不是函数,也不是变量,而是 C 语言预处理阶段处理的内容

举一个简单的 demo:

1
2
3
4
5
6
7
8
#include <stdio.h>

#define Hina 947

int main() {
printf("%d\n", Hina);
return 0;
}

#define Hina 947 这就是最简单的宏,预处理器会把 Hina 替换成 947,所以编译器实际看到的代码大致相当于:

1
printf("%d\n", 947);

除此之外,宏也可以定义表达式,甚至携带参数,比如:

1
2
3
4
5
6
7
8
9
#include <stdio.h>

#define ADD(a,b) a+b

int main() {
int c = ADD(1,1);
printf("%d\n", c); //输出2
return 0;
}

看到这里相信你已经对宏有了一个初步的理解,咋镇强?!

img

但是其实宏定义真的安全吗,事实上它是 C 语言中看似简单、实则暗礁密布的重灾区,这就是今天每日一题的重点,让我们继续往下看

0x02 不是凭啥

请先想想下面这个程序会输出什么结果

1
2
3
4
5
6
7
8
#include <stdio.h>
#define SQUARE(x) x * x

int main() {
int a = 3;
printf("%d\n", SQUARE(a + 1));
return 0;
}

在心中有个预期的答案以后,再试试用你的 devC++ 跑一下,看看真正的运行结果是什么

what?!这 tm 为啥和我想的不一样啊,不应该输出 16 吗

img

别急,记得我一开始说的吗:

在程序正式编译之前,由预处理器按照规则进行文本替换的东西

0x03 进入正题

咳咳扯远了,来看看今天的每日一题

  1. 为什么上面的程序中会出现这种情况,如果要正确地输出 16 应该怎么改
  2. 思考以下程序的运行结果,并说说为什么会出现这种情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

#define ADD(a, b) a + b
#define SQUARE(x) x * x

int main(void)
{
int result = SQUARE(ADD(2, 3));

printf("result = %d\n", result);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

#define MAX(a, b) a > b ? a : b

int main(void)
{
int a = 3;
int b = 5;

int result = 2 * MAX(a, b) + 1;

printf("result = %d\n", result);

return 0;
}
1
2
3
4
5
6
7
8
9
#include <stdio.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main() {
int x = 3, y = 4;
int result = MAX(x++, y++);
printf("result = %d, x = %d, y = %d\n", result, x, y);
return 0;
}
  1. 宏定义完全安全吗,什么是宏定义的”优先级灾难”,我们应该如何避免宏定义的”优先级灾难”,规范使用宏?

0xa6 写在后面

小朋友们你们好啊 我是你们最喜欢的bn叔叔
看完了今天的每日一题是不是感觉学到了一些的很有趣但是其实没什么用宏定义冷知识呢?想了些和c语言相关的也比较有意思的玩意想让更多同学参与进来
好吧其实也没什么特别想说的了只是想水点字数,0xa6是什么意思我也不知道

img