相关段落可在C90 ISO 9899:1990中找到6.1.2.5类型:
“[..]涉及无符号操作数的计算永远不会溢出,因为[...]”
因此9899:1990 6.3不能适用,因此不能是未定义的行为。
感谢Keith Thompson帮助我阅读。 : - )
[2014-03-14] 显然,无符号短整数可能会溢出,导致未定义的行为,具体取决于目标环境。如果短无符号整数被算术提升为int,则会发生这种情况。详细信息请参阅updated answer以及supercat的注释。感谢两者。 : - )
首先,抱歉我的英语不好......我尽我所能。这是我的第一个问题,我认为这是一个非常愚蠢的问题。
由于一些可悲的原因,我的公司仍然坚持使用ANSI C90(ANSI / ISO 9899:1990),所以我手中有这个标准的旧版本,但仍然缺少修正和修正。
我有一个非常简单的问题,并且在我学习的时候已经非常清楚地知道答案 - 直到我尝试在标准中阅读它。
如果我在添加上有无符号整数溢出会发生什么。请看这段代码:
uint32_t a,b,c;
b = UINT_MAX;
c = UINT_MAX;
a = b + c; /* Overflow here - undefined behavior? */
我所知道的就是,只要需要,无符号整数就会包裹起来,一切都很好,但并非总是如此。
现在我正在寻找标准中的相应部分。
当然,ISO 9899:1990 6.2.1.2描述了无符号整数的转换,无论何时转换。还有一点6.2.1.5“通常的算术转换”,它描述了类型如何变得更宽,主要是表达式的两个操作数具有相同的类型。
现在有6.3个“表达式”与我有关。我引用:
“[...] 如果在评估表达式期间发生异常(即,如果出现异常) 结果不是数学定义或不在可表示的范围内 对于它的类型)行为是不明确的。 [...]“
关于加法运算符的第6.3.6章说:
没有说,结果值被转换为结果类型 - 因此6.2.1.2不适用。但是这个价值显然会溢出,其中6.3步。
据我所知 - 根据ISO 9899:1990,这是未定义的行为。我错过了什么? Corrigendae中有什么东西吗?我是否错过了标准中的一行或一行?
我现在很困惑。 : - )
关于, 标记
[2014-03-03] 解决了
[2014年3月3日] 的 所以,多亏了Acme,我现在有一个明确而完整的答案 for ANSI C99 (见答案: "Is unsigned integer subtraction defined behavior":明确定义的行为符合预期。虽然我也期望对于ANSI C90 ,但鉴于上面的文字段落,我仍然无法从ISO 9899:1990的文本中读出它。所以我认为我的问题目前还没有答案。
编辑:Just Typos | Edit2:添加C90&标准标签| Edit3:添加问题更新| Edit4:添加已解决的部分|编辑5:添加答案链接:-) | Edit6:更新短无符号整数溢出|编辑7:一些拼写错误
答案 0 :(得分:6)
该区域从C90到C99,或从C99到C11没有显着变化。
C90 6.1.2.5(没有段落编号,但它是PDF第23页的第一段)说:
涉及无符号操作数的计算永远不会溢出,因为 结果无法由结果无符号整数表示 type是以大于最大值的数量减少的模数 可以由结果无符号整数类型表示的值。
几乎相同的措辞(短语“产生无符号整数类型”改变了 “结果类型”出现在C99和C11标准的6.2.5第9段中。
唯一重要的变化(我知道)是C99中关于签名转换的补充。在C90中,如果有符号或无符号值转换为有符号整数类型,并且结果无法在目标类型中表示,则结果是实现定义的。在C99和C11中,结果是实现定义的,或者引发实现定义的信号。 (我不知道任何利用许可来发出信号的编译器。)
正如supercat在评论中指出的那样,两个unsigned short
值的乘法可以溢出。假设short
是16位,int
是32位,并且整数表示是典型的(对于有符号类型的2的补码,没有填充位)。然后给出:
unsigned short US = USHRT_MAX; // 65536
表达式中的两个操作数
us * us
从unsigned short
升级到int
(因为int
可以包含unsigned short
类型的所有可能值 - 但产品近2 32 ,不适合32位签名 int
。
(在20世纪80年代后期的C标准化过程中,委员会必须在“保值”和“无符号保留”整数促销之间做出选择。他们选择前者。使用无符号保留语义,{{1}操作数将被提升为unsigned short
,并且不会发生此问题。)