c++ - 溢出的签名/未签名分配及其结果

标签 c++ unsigned signed integer-overflow

我正在阅读 Stroustrup 的书“C++ 编程语言第 4 版”,并且有三个关于溢出赋值的问题(特别是有符号/无符号字符,如书中所示)。首先,按照标准的5/4段落:

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

(除非目标变量是无符号的 - 在这种情况下结果已明确定义)。但是这个定义是否也适用于作业?

因为我觉得书中有很多相反的说法,都在第6章。第一个对应上述段落,但以下评论不是:

Variables of the three char types can be freely assigned to each other. However, assigning a too large value to a signed char is still undefined. For example:

void g(char c, signed char sc, unsigned char uc)
{
    c = 255; //implementation-defined if plain chars are signed and have 8 bits
    c = sc; //OK
    c = uc; //implementation-defined if plain chars are signed and if uc's value is too large
    sc = uc; //implementation-defined if uc's value is too large
    uc = sc; //OK: conversion to unsigned
    sc = c; //implementation-defined if plain chars are unsigned and if c's value is too large
    uc = c; //OK: conversion to unsigned
}

第一个问题:既然分配太大的值是UB,那么为什么评论说它是实现定义的?

接下来我们有如下例子:

To be concrete, assume that a char is 8 bits:

signed char sc = -160;
unsigned char uc = sc; //uc == 116 (because 256-160==116)
cout << uc; //print 't'

第二个问题:除了第一个赋值应该是UB之外,作者到底用了什么公式得出116?在我的测试中,uc 得到了 96 的值。

最后一句话:

An integer can be converted to another integer type. If the destination is signed, the value is unchanged if it can be represented in the destination type; otherwise, the value is implementation-defined:

signed char sc = 1023; //implementation-defined

Plausible results are 127 and -1.

第三个问题:同样,除了这与之前关于UB所说的相反之外,为什么可能的结果是127和-1?我猜它与一个和两个的补码有关,但使用的精确公式是什么?

最佳答案

1) 实现定义的是“一类UB”——换句话说,它仍然是UB,只是实现负责解释它是如何工作的,而不是“你不能完全依赖这个操作” .因此,如果您分配超出范围的 char 值,编译器仍然可以破坏您的计算机。但实现也可以定义“将其截断为 8 位等效值”。

2) 256 - 160 = 96 在我的计算器上。我敢打赌它也在你身上。也许作者有不同的计算器?或者它是最后一分钟从 -150 更改为 -160 的那些东西之一,它忘记了更改最终结果。

3) 因为它是“实现定义的”,所以它几乎可以是任何东西。由于该值为十六进制的 0x3ff,我们可以将 0xff 或 0x7f 想象为合理的值,具体取决于实现决定如何做到这一点。我预计大多数编译器将使用 0xff 值。

关于c++ - 溢出的签名/未签名分配及其结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17976878/

相关文章:

java - 如何在 Java 中执行无符号到有符号的转换?

c - 签名和未签名不起作用

c++ - 如何解决 requires 子句不兼容

java long 数据类型转换为无符号值

c - C 中 unsigned int 的行为

c - C单位转换问题

c++ - 根据C++标准的多态对象的存储布局

c++ - 将 lambda 推送到 C++ STL 队列导致段错误

c++ - cudaMallocManaged 用于主机启动的变量

c++ - 是否有一些有意义的统计数据来证明保持有符号整数算术溢出未定义?