【问题标题】:Why does the expression below characterize a narrowing conversion?为什么下面的表达式表征缩小转换?
【发布时间】:2014-02-10 02:22:45
【问题描述】:

此表达式可在标准 (N3797) §8.5.4/7 中的示例中找到

unsigned int ui1 = {-1}; // error: narrows

鉴于 §8.5.4/7 及其第 4 个要点:

窄化转换是一种隐式转换:

  • 从整数类型或无作用域枚举类型到不能表示原始类型所有值的整数类型, 除非源是一个常量表达式,其值在 积分促销将适合目标类型。

我想说这里没有缩小范围,因为 -1 是一个常量表达式,其值在积分提升后适合无符号整数。

另请参阅 §4.5/1 关于整体推广

除 bool、char16_t、char32_t 或 wchar_t 其整数转换等级 (4.13) 小于 如果 int 可以表示所有,则 int 可以转换为 int 类型的纯右值 源类型的值;否则,源纯右值可以是 转换为 unsigned int 类型的纯右值。

从 4.13 开始,我们得到 -1(一个 int)的秩等于一个 unsigned int 的秩,因此它可以转换为一个 unsigned int。

编辑

不幸的是,Jerry Coffin 从这个帖子中删除了他的答案。我相信他走在正确的轨道上,如果我们接受在标准中的 change 之后的第 8.5.4/7 节中第 4 个要点的当前阅读是错误的事实。

【问题讨论】:

  • 没有。它已经是一个整数(有符号整数),转换后它的值不适合目标类型。 unisgned integer 不能代表 signed integer 的所有值,具体而言;它不能代表负值。
  • "-1 是一个常量表达式,它的整数提升后的值适合一个无符号整数。" - 不,-1 是 int 类型,因此,它不会被提升为任何东西。
  • @ElliottFrisch 如果您将无符号整数视为正整数则不能,如果您将其视为模整数则可以!!

标签: c++ c++11 language-lawyer narrowing


【解决方案1】:

intunsigned int没有整体提升,因此它仍然是不正确的。

这将是一个完整的转换

【讨论】:

  • 您能根据 §4.5/1 解释一下吗?
  • @WakeupBrazil 老实说,我不知道如何比文字更好地解释。它说出了我在答案中所说的内容,并且更加详细和详细。
  • @JohannesSchaub-litb 非常感谢您的大力帮助
  • @Joh:不是畸形,只是变窄了。
【解决方案2】:

窄化是从整数类型到整数类型的隐式转换,不能表示原始类型的所有值

从整数类型int 到整数类型unsigned int 的转换,当然不能代表原始类型的所有值——这里的标准是相当明确的。如果你真的需要它,你可以这样做

 unsigned int ui1 = {-1u};

这没有任何错误/警告,因为1uunsigned int 类型的文字,然后被否定。这在标准状态中被明确定义为 [expr.unary.op]

无符号量的负数是通过从 2n 中减去其值来计算的,其中 n 是提升的操作数中的位数。

-1 然而在否定之前和之后是一个int,因此它变成了一个缩小转换。 There are no negative literals;详情请见this answer

推广是,非正式地,将相同的值复制到更大的空间,所以这里不应该混淆,因为大小(signedunsigned)是相等的。即使您尝试将其转换为某种更大的尺寸,比如unsigned long long,它仍然是一个缩小转换,因为它不能真正代表负数。

【讨论】:

  • 我认为编译器可以合法地发出 -1u 警告。
  • 这很有趣。所以intunsigned int 正在缩小,同样的定义,unsigned intint 也在缩小?
  • 是的,对于unsigned x = 0u; signed y = {x}; GCC (4.8.1) 吐出:警告:在 {} 内将“x”从“unsigned int”缩小到“int”。
【解决方案3】:

标准措辞的更改旨在确认将负值转换为无符号类型是并且一直是缩小转换的理解。

非正式地,-1 不能在任何无符号类型的范围内表示,并且表示它的位模式如果存储在无符号 int 中,则表示的值不同。因此,这是一个缩小转换,不涉及提升/扩大。

这是关于阅读标准的精致艺术。像往常一样,编译器最清楚。

【讨论】:

  • Therefore this is a narrowing conversion and promotion/widening is not involved. 标准中哪里说积分促销不适用于这种情况?相反,我在问题中强调的要点特别提到了术语integral promotion
  • @Wake:S6.3.1.1 定义了整数提升。它们仅适用于较低等级的值或位字段,并且它们保留符号。它们从不将有符号整数转换为无符号整数。其他对整数提升的引用不会改变这个定义。
  • 我不知道草案 N3337 和 N3797 中有任何 6.3.1.1 或 S6.3.1.1。两个草案的第 4.5 节都定义了整体提升,我在问题中提到的段落是标准本节的第一段。根据本段,绝对可以将 -1 提升为无符号整数。这是因为 int 的等级等于 unsigned int 的等级(来自 §4.13)。
  • 糟糕。抱歉,我在那里使用 C 标准。不改变现状。我认为您正在阅读 S4.5 中的“否则”,就好像它适用于每个整数类型一样,但事实并非如此。它仅适用于最后一个 if,即表示所有值的位。由于 int 不是“小于 int 的等级”,因此该段落中的任何内容都不适用于 int。简而言之,int 永远不会被提升。
  • (+1) 你成功了!优秀的答案。 Tks
猜你喜欢
  • 2012-07-11
  • 2013-07-28
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2021-11-18
  • 1970-01-01
相关资源
最近更新 更多