面试题答案
一键面试参数类型检查
- 普通函数:
- 普通函数在编译时会对参数进行类型检查。如果传递给函数的参数类型与函数定义中参数的类型不匹配,编译器会发出警告或错误信息。这有助于发现代码中的类型错误,提高代码的健壮性。
- 例如:
#include <stdio.h>
// 普通函数定义
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 5); // 正确调用
// int wrongResult = add(3.5, 5); // 错误调用,会有编译错误,因为参数类型不匹配
return 0;
}
- 宏函数:
- 宏函数在预处理阶段进行替换,不会进行参数类型检查。只要宏函数的参数在语法上能正确替换到宏定义中,就可以通过预处理。这可能导致在运行时出现难以调试的错误,因为类型不匹配的问题不会在编译时被发现。
- 例如:
#include <stdio.h>
// 宏函数定义
#define ADD(a, b) ((a)+(b))
int main() {
int result = ADD(3, 5); // 正确使用
double wrongResult = ADD(3.5, 5); // 虽然这里类型不匹配,但宏替换时不会报错,运行时可能结果不符合预期
return 0;
}
参数求值顺序
- 普通函数:
- 在普通函数中,参数的求值顺序是由编译器决定的,并且在函数调用之前,所有参数都会被求值。不过,标准并没有严格规定参数的求值顺序,不同的编译器可能有不同的实现。但无论如何,在函数调用时,所有参数的值都是确定的。
- 例如:
#include <stdio.h>
int func(int a, int b) {
return a + b;
}
int main() {
int x = 2;
int y = 3;
int result = func(x++, ++y); // 虽然参数求值顺序不确定,但在函数调用时x和y的值是确定的
printf("result: %d\n", result);
return 0;
}
- 宏函数:
- 宏函数中参数的求值顺序是在宏展开时确定的。每次宏函数中的参数被使用时,都会重新求值。这可能导致一些意想不到的结果,特别是当参数中包含有副作用的表达式(如自增、自减运算符)时。
- 例如:
#include <stdio.h>
#define MULT(a, b) ((a)*(b))
int main() {
int x = 2;
int y = 3;
int result = MULT(x++, ++y);
// 宏展开后是 ((x++)*(++y)),x和y会多次求值,结果可能与预期不同
printf("result: %d\n", result);
return 0;
}
总结
普通函数在参数类型检查上更严格,能在编译时发现类型错误;而宏函数在预处理阶段替换,不进行类型检查。在参数求值顺序上,普通函数在调用前确定参数值,求值顺序由编译器决定但调用时参数值确定,宏函数在宏展开时求值,参数会多次求值,尤其在参数含副作用表达式时易产生意外结果。