【问题标题】:Can unsigned integer incrementation lead to undefined defined behavior?无符号整数增量会导致未定义的行为吗?
【发布时间】:2015-01-16 06:05:47
【问题描述】:

在阅读了 StackOverflow 上的32 bit unsigned multiply on 64 bit causing undefined behavior? 问题后,我开始思考对于小型无符号类型的典型算术运算是否会导致根据 C99 标准的未定义行为。

以如下代码为例:

#include <limits.h>

...

unsigned char x = UCHAR_MAX;
unsigned char y = x + 1;

x 变量被初始化为unsigned char 数据类型的最大值。下一行是问题:值x + 1 大于UCHAR_MAX 并且不能存储在unsigned char 变量y 中。

我相信以下是实际发生的情况。

  • 变量x首先被提升为数据类型int6.3.1.1/2部分),然后x + 1被评估为数据类型int

假设有一个实现,其中INT_MAXUCHAR_MAX 相同——x + 1 会导致有符号整数溢出。这是否意味着增加变量x,尽管它是无符号整数类型,但可能会由于可能的有符号整数溢出而导致未定义的行为?

【问题讨论】:

  • 如果sizeof(unsigned char) == sizeof(int),则适用第一种情况。
  • @chux 如果int 可以代表价值,为什么促销不会发生?
  • 我会回顾“6.3.1.8 通常的算术转换”这似乎首先适用“否则,如果具有无符号整数类型的操作数的等级大于或等于另一个类型的等级操作数,然后将带符号整数类型的操作数转换为无符号整数类型的操作数的类型。"这出现在“否则,如果带符号整数类型的操作数的类型可以表示无符号整数类型的操作数类型的所有值......”规则。
  • 我坐得更正了。如果INT_MAX &gt;= UCHAR_MAXunsigned char x 将按照“常规算术转换”转换为int
  • 假设这就是为什么代码应该使用unsigned char y = x + 1u

标签: c language-lawyer c99 undefined-behavior


【解决方案1】:

根据我对标准的阅读,使用 15 位 char 的实现可以合法地将 int 存储为 15 位大小,并使用第二个 15 位字来存储符号以及 14 位填充;在这种情况下,unsigned char 将保存 0 到 32,767 的值,int 将保存从 -32,767 到 +32,767 的值。将 1 添加到 (unsigned char)32767 确实是未定义的行为。如果将 32,767 替换为 UCHAR_MAX,任何更大的 char 大小都可能出现类似情况。

然而,与另一篇文章中提到的与无符号整数乘法相关的实际问题相比,这种情况不太可能发生。

【讨论】:

    猜你喜欢
    • 2014-08-11
    • 2016-09-04
    • 1970-01-01
    • 2017-04-08
    • 2017-01-23
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多