首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从8位整数中得到大于8位大小的值?

如何从8位整数中得到大于8位大小的值?
EN

Stack Overflow用户
提问于 2013-04-20 22:02:58
回答 9查看 7.4K关注 0票数 119

我在这个小宝石后面找到了一只非常讨厌的虫子。我知道根据C++规范,签名溢出是未定义的行为,但只有当值扩展到位宽sizeof(int)时才会发生溢出。据我所知,增量char不应该像sizeof(char) < sizeof(int)那样是未定义的行为。但这并不能解释c是如何得到一个不可能的价值的。作为一个8位整数,c如何保存大于其位宽的值?

代码

代码语言:javascript
复制
// Compiled with gcc-4.7.2
#include <cstdio>
#include <stdint.h>
#include <climits>

int main()
{
   int8_t c = 0;
   printf("SCHAR_MIN: %i\n", SCHAR_MIN);
   printf("SCHAR_MAX: %i\n", SCHAR_MAX);

   for (int32_t i = 0; i <= 300; i++)
      printf("c: %i\n", c--);

   printf("c: %i\n", c);

   return 0;
}

输出

代码语言:javascript
复制
SCHAR_MIN: -128
SCHAR_MAX: 127
c: 0
c: -1
c: -2
c: -3
...
c: -127
c: -128  // <= The next value should still be an 8-bit value.
c: -129  // <= What? That's more than 8 bits!
c: -130  // <= Uh...
c: -131
...
c: -297
c: -298  // <= Getting ridiculous now.
c: -299
c: -300
c: -45   // <= ..........

去看看理想国。

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2013-04-20 22:24:04

这是一个编译器错误。

虽然对于未定义的行为获得不可能的结果是一个有效的结果,但实际上在代码中没有未定义的行为。所发生的是编译器认为行为是未定义的,并相应地进行优化。

如果c被定义为int8_t,并且int8_t提升为int,那么c--应该在int算法中执行减法c - 1并将结果转换回int8_tint中的减法不会溢出,并且将超出范围的积分值转换为另一种积分类型是有效的.如果对目标类型进行签名,则结果是实现定义的,但它必须是目标类型的有效值。(如果目标类型是无符号的,则结果是定义良好的,但在这里不适用。)

票数 111
EN

Stack Overflow用户

发布于 2013-04-21 04:01:41

编译器可能有不符合标准的错误,因为还有其他的需求。编译器应该与其自身的其他版本兼容。它还可以在某些方面与其他编译器兼容,并符合大多数用户所持有的关于行为的一些信念。

在这种情况下,它似乎是一个一致性错误。表达式c--应该以类似于c = c - 1的方式操作c。在这里,右边的c值被提升为int类型,然后进行减法。由于cint8_t的范围内,这种减法不会溢出,但是它可能产生一个超出int8_t范围的值。当此值被赋值时,转换将返回到int8_t类型,因此结果符合c。在超出范围的情况下,转换具有实现定义的值.但超出int8_t 范围的值不是一个有效的实现定义值。实现不能“定义”一个8位类型突然容纳9位或更多位。的值为实现-定义意味着在int8_t范围内的东西被产生,并且程序继续。是C标准,因此允许诸如饱和算法(在DSP上常见)或环绕(主流体系结构)等行为。

编译器在操作小整数类型(如int8_tchar )的值时使用更广泛的底层机器类型。当执行算法时,在这种更宽的类型中,可以可靠地捕获超出小整数类型范围的结果。为了保持变量为8位类型的外部可见行为,必须将更广泛的结果截断到8位范围内。要做到这一点,需要显式代码,因为机器存储位置(寄存器)大于8位,并且对较大的值很满意。在这里,编译器忽略了对值进行规范化,而只是按原样将其传递给printfprintf中的转换说明符printf不知道参数最初来自int8_t计算;它只是在处理int参数。

票数 15
EN

Stack Overflow用户

发布于 2013-04-20 22:16:18

我不能把它放在评论中,所以我把它作为一个回答。

由于一些非常奇怪的原因,--运算符恰好是罪魁祸首。

我测试了发布在Ideone上的代码,用c = c - 1替换了c = c - 1,其值保持在-128 . 127范围内

代码语言:javascript
复制
c: -123
c: -124
c: -125
c: -126
c: -127
c: -128 // about to overflow
c: 127  // woop
c: 126
c: 125
c: 124
c: 123
c: 122

怪胎?我不太清楚编译器对像i++i--这样的表达式做了什么。它可能会将返回值提升到int并传递给它。这是我能得出的唯一合乎逻辑的结论,因为你实际上得到的值不适合8位。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16125660

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档