pax*_*blo 13 c iso language-lawyer
在最近回答另一个问题时,我发现了代码的问题,例如:
int n;
scanf ("%d", &n);
Run Code Online (Sandbox Code Playgroud)
使用strtol
,您可以检测溢出,因为在这种情况下,插入的最大值被设置为n
并errno
设置为指示溢出,如下所示C11 7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions /8
:
如果正确的值超出可表示值的范围,则返回LONG_MIN,LONG_MAX,LLONG_MIN,LLONG_MAX,ULONG_MAX或ULLONG_MAX(根据值的返回类型和符号,如果有),并且宏ERANGE的值为存储在errno中.
但是,在标准处理的部分中scanf
,具体来说C11 7.21.6.2 The fscanf function /10
,我们看到:
如果此对象没有适当的类型,或者无法在对象中表示转换结果,则行为未定义.
现在,对我而言,这意味着可以返回任何值,并且没有提到errno
任何设置.这一点已经曝光,因为上面链接问题的提问者进入9,999,999,999
了32位int
并且返回1,410,065,407
,一个值太小,表明它只是在类型的极限处缠绕.233
当我尝试它时,我回来了2,147,483,647
,最大可能的32位无符号值.
所以我的问题如下.在使用scanf
函数族时,如何以可移植的方式检测积分溢出?它甚至可能吗?
现在,我要指出,我的系统(Debian的7)上,errno
是实际设置为ERANGE
在这种情况下,但我能找到什么的标准是强制要求这一点.此外,从返回值scanf
是1
,表示扫描项目的成功.
唯一可移植的方法是指定字段宽度,例如使用"%4d"
(保证甚至适合16位int
)或通过在字段宽度为的运行时构建格式字符串(int)(log(INT_MAX) / log(10))
.这当然也拒绝例如32000,尽管它适合16位int
.所以不,没有令人满意的便携方式.
POSIX在这里没有指定更多,也没有提及ERANGE
.
此联机帮助页errno
仅在以下情况下提及设置EOF
; glibc文档根本没有提到ERANGE
.
这留下了一个问题,建议初学者阅读整数,我不知道.scanf
有太多未定义和未指定的方面真正有用,fgets
不能用于生产代码,因为你不能正确处理0字节,strtol
与朋友进行便携式错误检查比自己实现功能需要更多的行(并且很容易出错) ).atoi
对于整数溢出,行为也是未定义的.
归档时间: |
|
查看次数: |
798 次 |
最近记录: |