Vic*_*cky 39
考虑典型的"最大"宏,与功能:
#define MAX(a,b) a < b ? a : b
int max(int a, int b) {return a < b ? a : b;}
当人们说宏在函数的方式不是类型安全时,这就是人们的意思:
如果函数的调用者写入
char *foo = max("abc","def");
编译器会发出警告.
然而,如果宏的调用者写道:
char *foo = MAX("abc", "def");
预处理器将替换为:
char *foo = "abc" < "def" ? "abc" : "def";
这将编译没有问题,但几乎肯定不会给你想要的结果.
另外当然副作用也不同,请考虑功能案例:
int x = 1, y = 2;
int a = max(x++,y++); 
max()函数将对x和y的原始值进行操作,后递增将在函数返回后生效.
在宏案例中:
int x = 1, y = 2;
int b = MAX(x++,y++);
第二行被预处理给出:
int b = x++ < y++ ? x++ : y++;
同样,没有编译器警告或错误,但不会是您期望的行为.
mar*_*ark 11
好吧,他们不是直接类型安全的...我想在某些场景/用法中你可以说他们可以间接(即结果代码)类型安全.但你当然可以创建一个用于整数的宏并传递它的字符串...处理宏的预处理器当然不关心.编译器可能会阻塞它,具体取决于使用情况......
Tom*_*ner 11
宏不是类型安全的,因为它们不了解类型.
你不能告诉宏只采取整数.预处理器识别宏用法,它用一组令牌替换一个令牌序列(带有参数的宏).如果使用正确,这是一个强大的工具,但它很容易使用不正确.
使用函数,您可以定义一个函数void f(int, int),如果您尝试使用f的返回值或传递字符串,编译器将标记.
用宏 - 没有机会.唯一的检查是给出正确数量的参数.然后它适当地替换令牌并传递给编译器.
#define F(A, B)
允许你打电话F(1, 2),F("A", 2)或者F(1, (2, 3, 4))或者......
如果宏中的某些内容需要某种类型的安全性,您可能会从编译器中获得错误,或者您可能不会收到错误.但这不是预处理器.
将字符串传递给期望数字的宏时,您可以获得一些非常奇怪的结果,因为您最终可能会使用字符串地址作为数字而不会从编译器发出吱吱声.