将下溢的无符号整数与 -1 进行比较是否定义明确?

2024-01-02

Consider the following:

size_t r = 0;
r--;
const bool result = (r == -1);

比较结果是否初始化result有明确的行为吗?
它的结果是true,如我所料?


This Q&A was written because I was unsure of two factors in particular.
They may both be identified by use of the term "crucial[ly]" in my answer.

This example is inspired by an approach for loop conditions when the counter is unsigned:
for (size_t r = m.size() - 1; r != -1; r--)


size_t r = 0;
r--;
const bool result = (r == -1);

严格来说,价值result是实现定义的。实际上,几乎可以肯定的是true;如果有一个实现,我会感到惊讶false.

的价值r after r--的值是SIZE_MAX,定义在中的宏<stddef.h> / <cstddef>.

为了比较r == -1, the 常见的算术转换对两个操作数都执行。通常算术转换的第一步是应用积分促销到两个操作数。

r属于类型size_t,实现定义的无符号整数类型。-1是类型的表达式int.

在大多数系统上,size_t至少与int。在此类系统上,积分促销会带来以下价值:r要么转换为unsigned int或保留其现有类型(前者可能发生,如果size_t具有相同的宽度int,但转化排名较低)。现在,左操作数(无符号)至少具有右操作数(有符号)的秩。右操作数转换为左操作数的类型。此转换产生的值与r,因此相等比较产生true.

这是“正常”情况。

假设我们有一个实现,其中size_t是 16 位(假设它是typedef for unsigned short) and int是32位的。所以SIZE_MAX == 65535 and INT_MAX == 2147483647。或者我们可以有一个 32 位的size_t和 64 位int。我怀疑是否存在任何此类实现,但标准中没有任何内容禁止它(见下文)。

现在比较的左侧有类型size_t和价值65535. Since signed int可以代表type的所有值size_t,积分促销将价值转换为65535 of type int。两侧==运算符有类型int,所以与通常的算术转换无关。该表达式相当于65535 == -1,这显然是false.

正如我提到的,这种事情不太可能发生在类型表达式中size_t-- 但对于较窄的无符号类型很容易发生这种情况。例如,如果r被声明为unsigned short, or an unsigned char,甚至是一个简单的char在该类型有符号的系统上,result可能会是false。 (我说可能是因为short甚至unsigned char可以具有相同的宽度int, 在这种情况下resulttrue.)

在实践中,您可以通过显式执行转换而不是依赖于实现定义的常见算术转换来避免潜在的问题:

const bool result = (r == (size_t)-1);

or

const bool result = (r == SIZE_MAX);

C++11标准参考:

  • 5.10 [expr.eq] 相等运算符
  • 5.9 [expr.rel]关系运算符(指定执行通常的算术转换)
  • 5 [expr] 表达式,第 9 段:常用算术转换
  • 4.5 [conv.prom]积分促销
  • 18.2 [支持类型]size_t

18.2 第 6-7 段:

6 类型size_t是实现定义的无符号整数类型 它足够大以包含任何对象的字节大小。

7 [ Note:建议实现选择类型ptrdiff_t and size_t其整数转换等级 (4.13) 为 no 大于signed long int除非尺寸更大 必须包含所有可能的值。 ——尾注]

So there's no prohibition on making size_t narrower than int. I can almost plausibly imagine a system where int is 64 bits, but no single object can be bigger than 232-1 bytes so size_t is 32 bits.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将下溢的无符号整数与 -1 进行比较是否定义明确? 的相关文章

随机推荐

  • 在数据表对象中使用 ColumnHidden 属性

    我有一个微软访问形式与数据表子表单 使用代码 我改变了列隐藏其各个列的属性 但是 当我关闭表单时 系统会询问我是否保存数据表表格的表格布局 如何阻止表单不断要求用户相同的表格布局 我是否别无选择 只能将数据表更改为常规子表单 如果您始终隐藏
  • 将地图的所有元素复制到另一个地图中

    Given var dst src map K V 我可以复制所有条目src into dst通过做 for k v range src dst k v 有没有更惯用的方法来做到这一点 copy仅适用于切片 并且string作为来源 对我来
  • R 向量大小限制:“.C 中不支持长向量(参数 5)”

    我有一个非常大的矩阵 我试图在有足够内存的服务器上通过 glmnet 运行 即使在达到某一点的非常大的数据集上它也能正常工作 之后我收到以下错误 Error in elnet x long vectors argument 5 are no
  • BOOL 设置不正确,调试输出混乱

    我试图在 Xcode 中设置一个 BOOL 但由于某种原因 它明显拒绝工作 没有其他东西在设置这个布尔值 只有这一个实例 我的代码如下 h interface SuspectsViewController UIViewController
  • 使用 ngModels 从组件到视图的带有数组的角度绑定对象

    我尝试将我的模型绑定到我的视图上 但是当我提交表单时遇到问题 我没有数组 但有很多属性 成分 export class QuizFormAddQuestionComponent implements OnInit public questi
  • Angular 2 - 如何传递 URL 参数?

    我在 Angular 2 中创建了一个单页抵押计算器应用程序 它对我来说就像一个学习游乐场 试图更习惯当前工作中使用的技术堆栈 http www mortgagecalculator123 com http www mortgagecalc
  • 在 php:7.4-fpm 映像上安装 PHP-zip

    我想在我的 docker 映像上安装 php zip 最终目标是使用 PhpWord 库 我使用 php 7 4 fpm 它在 Debian 上运行 在我的 dockerfile 中 我使用以下命令 RUN apt get update d
  • WebDriver Java:将现有的 WebDriver 浏览器会话重新附加到驱动程序实例

    我正在寻找一种方法将现有的 webdriver 浏览器会话重新附加到驱动程序实例 以便我可以再次控制浏览器 到目前为止 我已经尝试过以下操作 I 参考 https stackoverflow com a 38827934 2285470 h
  • 浮动div在固定高度容器中从上到下然后从左到右

    我试图在固定高度的容器中从上到下 从左到右垂直浮动 DIV 垂直浮动DIV从上到下按行排列 https stackoverflow com questions 16316329 div vetically floating div arra
  • 如何使用 Json 对象的动态属性名称

    我们如何使 JSON 属性名称动态化 例如 public class Value JsonProperty value value private String val public void setVal String val this
  • R通过lapply命令从乘法回归中提取回归系数

    我有一个包含多个变量的大型数据集 其中一个是状态变量 每个状态编码为 1 50 我想对数据集的其余 27 个变量 总共 55 个变量 运行 28 个变量的回归 并且针对每个州 换句话说 对 covariate1 covariate2 cov
  • MySQL 外键约束 - 整数列

    我有一个整数列 我想向其中添加外键约束 唯一的问题是 如果该列没有 不需要值 默认情况下 MySQL 会输入 0 值 这显然破坏了外键约束 因为主表中没有 PK 为 0 的记录 我怎样才能克服这个问题 您可能需要设置外键以接受NULL值 并
  • 创建 debian 包

    我已经在 debian 网站上检查了创建包的情况 但是 它并不容易理解 因为它没有给出逐步的过程 请帮助我如何创建 Debian 软件包 如果可以的话有详细的步骤就更好了 目标是创建一个包 将 shell 脚本简单地放置在我想要的位置 1
  • 如何从 Scrapy 中的请求中获取响应?

    有什么办法可以让我得到response body来自scrapy中的Request函数 我有这个 request Request http www example com callback self mytest def mytest se
  • NA 替换为空格

    我使用了相同的方法将 NA 替换为空格或其他字符 但由于某种原因 这个方法不起作用 我想将数据框中的 NA 替换为空白 年份和年度列 我究竟做错了什么 shad 92 lt structure list year c 1992 NA NA
  • 通过图像中的边界框提取选定的文本

    我正在尝试通过图像上的边界框获取选定的文本 就像如果仅通过边界框选择单词一样 我想获取该文本并将其转换为文本文件 请查看我的代码并进行一些审查 以便我可以实现该功能 到目前为止 我已经将 PDF 文件转换为在文本上带有边框的图像 impor
  • 如何获取oracle中所有物化视图的列表

    如何获取所有物化视图的列表 尝试这个 SELECT FROM all snapshots 代替all snapshots您还可以使用all mviews view
  • 延迟加载角度的解析器

    有没有办法在加载延迟加载模块之前添加解析器 我尝试添加resolve到路由配置 但它没有被触发 也没有在网络上找到任何有用的东西 任何帮助 将不胜感激 import NgModule from angular core import Rou
  • 如何运行docker守护进程?

    我正在尝试使用命令运行 docker 守护进程 docker d 但我在控制台收到 unknown shorthand flag d in d 我应该怎么做才能运行 docker 守护进程 如果您停止了该服务 则需要以下命令才能重新启动它
  • 将下溢的无符号整数与 -1 进行比较是否定义明确?

    Consider the following size t r 0 r const bool result r 1 比较结果是否初始化result有明确的行为吗 它的结果是true 如我所料 This Q A was written bec