规则1:
不通过链接创建通用字符串。
C11标准:如果匹配通用字符名称的字符序列由符号链接生成,将产生未定义行为。
#define assign(uc1,uc2,val) uc1##uc2 = val void func(){ int u0401; assign(u04,01,4); printf("u0401 = %d\n",u0401); } int main(){ func(); }
此结果是未定义的,不要使用链接诶字符串来赋值。 规则2: 避免使用不安全的宏参数
#define ABS(x) (((x) < 0) ? -(x) : (x))
void fun(int n){
/*
* n++;
* ABS(n); right
*/
ABS(n++);/*erro*/
}
注意n的加减。 解决方案一: 我们可以写一个内联函数或者写一个静态函数来代替此宏。 解决方案二: 使用范型编程_Generic 参数,范型选择不求值,所以我们的值只会求一次。
#include<stdio.h>
#include<complex.h>
#include<math.h>
static inline long labs(long v){
return v < 0 ? -v : v;
}
static inline int ilabs(int v){
return v < 0 ? -v : v;
}
static inline short slabs(int v){
return v < 0 ? -v : v;
}
#define ABS(v) _Generic(v,long : labs ,\
int : ilabs ,\
short: slabs)(v)
void fun(int n){
int m = ABS(++n);
}
int main(){
fun(10);
}
解决方案三: 使用GCC 扩展,但是会带来平台问题。
#define ABS(x) __extension__ ({__typeof(x) tmp = x ;\
tmp < 0 ? -tmp : tmp;})
规则: 不要在类函数的宏调用中使用预处理器指令
void func(const char * src){
char *dest;
memcpy(dest,src,
#ifdef A
12
#else
13
#endif);
}
其实能写出这种代码的人脑洞也是大的没谁了,我感觉这都不关乎安全问题了。 解决方法很简单,写完整就好了。