面试题答案
一键面试- #运算符 - 字符串化:
- 作用:#运算符用于将宏参数转换为字符串常量。
- 代码示例:
#include <stdio.h>
#define STRINGIFY(x) #x
int main() {
int num = 10;
printf("%s\n", STRINGIFY(num));
return 0;
}
- 解释:在上述代码中,
STRINGIFY(num)
会将num
转换为字符串"num"
,然后通过printf
输出。
- ##运算符 - 标记连接:
- 作用:##运算符用于将两个标记连接成一个新的标记。
- 代码示例:
#include <stdio.h>
#define CONCAT(a, b) a##b
int main() {
int num12 = 20;
printf("%d\n", CONCAT(num, 12));
return 0;
}
- 解释:在上述代码中,
CONCAT(num, 12)
会将num
和12
连接成num12
,从而能够正确访问num12
变量并输出其值。
- 复杂宏定义中可能遇到的问题及解决方案:
- 问题:
- 参数优先级问题:在复杂宏中,参数的优先级可能导致错误。例如:
- 问题:
#define MULTIPLY(a, b) a * b
#define COMPLEX_MACRO(x) MULTIPLY(x + 1, x - 1)
如果调用 COMPLEX_MACRO(5)
,实际展开为 5 + 1 * 5 - 1
,由于乘法优先级高于加法和减法,结果不是预期的 (5 + 1) * (5 - 1)
。
- 递归展开问题:当宏定义中存在递归展开可能时,会导致预处理器无限循环。例如:
#define EXPAND_ME(x) EXPAND_ME(x)
- 解决方案:
- 参数优先级问题:在宏定义中使用括号确保正确的运算顺序。例如,修改
MULTIPLY
宏为#define MULTIPLY(a, b) ((a) * (b))
,这样COMPLEX_MACRO(5)
展开为((5 + 1) * (5 - 1))
,能得到正确结果。 - 递归展开问题:确保宏定义不会导致无限递归,仔细检查宏的逻辑,避免自我调用无终止情况。在宏定义中添加条件判断来控制递归深度,例如:
- 参数优先级问题:在宏定义中使用括号确保正确的运算顺序。例如,修改
#define MAX_DEPTH 5
#define EXPAND_ME(x, depth) \
(depth > MAX_DEPTH? x : EXPAND_ME(x, depth + 1))
这样可以在达到最大深度后停止递归展开。