【发布时间】:2016-05-17 00:56:39
【问题描述】:
考虑以下程序 (C99):
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
int main(void)
{
printf("Enter int in range %jd .. %jd:\n > ", INTMAX_MIN, INTMAX_MAX);
intmax_t i;
if (scanf("%jd", &i) == 1)
printf("Result: |%jd| = %jd\n", i, imaxabs(i));
}
现在据我了解,这包含易于触发的未定义行为,如下所示:
Enter int in range -9223372036854775808 .. 9223372036854775807:
> -9223372036854775808
Result: |-9223372036854775808| = -9223372036854775808
问题:
当用户输入错误的数字时,这真的是未定义的行为吗,例如“允许代码触发任何代码路径,任何代码都被编译器喜欢”?还是其他的不完全定义?
一个学究气的程序员如何防范这种情况,不做任何标准不能保证的假设?
(有一些相关的问题,但我没有找到一个回答上面问题2的问题,所以如果你建议重复,请确保它回答了。)
【问题讨论】:
-
请注意,输入超出范围的 int 也会导致未定义的行为。如果你想避免 UB,你不能使用任何风格的
%d或其他整数或浮点 scanf 说明符。使用strto家族。而且只有一种未定义的行为,就是不好的。 -
@M.M 还有实现定义的行为,未指定但有效的值,也许还有一些其他更温和的未定义行为的替代方案。但是,我是否误解了,或者您是说用于有符号数或浮点数的 scanf 隐式包含用户可触发的 UB?参考?
-
是的,用户可以通过输入一个超出被扫描整数范围的值来触发 UB。请参阅 C 标准中
fscanf的规范。在 C11 中是 7.21.6.2/10,“如果转换的结果不能在对象中表示,则行为未定义”。所以scanf系列在大多数情况下不适合在生产中使用 -
我记得很多年前在我的编程入门课上,第一个作业是编写一个程序来将两个数字相加,这两个数字可以是正数也可以是负数。我尽职尽责地编写了代码,然后意识到可能存在上溢和下溢,因此我编写了代码来检测并通知用户是否发生。我想可以做类似的事情来满足你的第二个问题。
标签: c undefined-behavior absolute-value