如何利用MAX_BUF_LEN宏避免scanf缓冲区溢出?格式串引号有何差异?
问题解答
一、怎么避免scanf里用魔法数字?
直接用宏MAX_BUF_LEN就行,但得利用C预处理器的字符串化和字符串拼接特性:
方法1:预处理器字符串化
#define MAX_BUF_LEN 32 char buf[MAX_BUF_LEN]; scanf("%" #MAX_BUF_LEN "[^\n]", buf);
这里的#MAX_BUF_LEN是预处理器的字符串化操作,会把宏的值(比如32)直接转成字符串"32",预编译后整个格式串就变成"%32[^\n]",完美替换魔法数字。
方法2:动态构造格式串(更灵活)
如果需要给字符串终止符留空间(毕竟buf的长度要包含'\0',所以实际最多读MAX_BUF_LEN-1个字符),可以用snprintf先拼出格式串:
#define MAX_BUF_LEN 32 char buf[MAX_BUF_LEN]; char fmt[32]; // 用%%转成单个%,MAX_BUF_LEN-1是给'\0'留位置 snprintf(fmt, sizeof(fmt), "%%%d[^\n]", MAX_BUF_LEN - 1); scanf(fmt, buf);
这种方式适合宏的值需要计算的场景,比直接字符串化更灵活。
二、数字前后加引号和不加的区别
你看到的%"512"[^\n]和%512[^\n],本质上是一回事:
%"512"[^\n]其实是把格式串拆成了三个相邻的字符串:"%"、"512"、"[^\n]",C预处理器会自动把相邻的字符串字面量拼接成一个完整的串,最终就是"%512[^\n]"。%512[^\n]是直接写完整的格式串,没有拆分。
两种写法运行起来完全没区别,前者只是用了字符串拆分拼接的写法而已。但如果要替换成宏的话,必须用第一种拆分+字符串化的方式,才能把宏的值代入格式串里。
内容的提问来源于stack exchange,提问作者truberfighter
相关产品推荐
相关产品推荐

