20

考虑以下代码:

template<bool> class StaticAssert;
template<> class StaticAssert<true> {};
StaticAssert< (-1 < sizeof(int)) > xyz1; // Compile error
StaticAssert< (-1 > sizeof(int)) > xyz2; // OK

为什么是-1 > sizeof(int)真的?

  1. 是不是真的-1晋升为unsigned(-1)然后unsigned(-1) > sizeof(int)
  2. -1 > sizeof(int)如果sizeof (int) 是 4 是真的吗?-1 > size_t(4)如果是这样,为什么-1 > size_t(4)是假的?

这是符合 C++ 标准的吗?

4

4 回答 4

15

以下是标准 (ISO 14882) 如何解释 abort -1 > sizeof(int)

关系运算符 `>' 在 5.9 (expr.rel/2) 中定义

通常的算术转换是在算术或枚举类型的操作数上执行的。...

通常的算术转换在 5 (expr/9) 中定义

...该模式称为通常的算术转换,其定义如下:

  • 如果任一操作数是 long double 类型,...
  • 否则,如果任一操作数是双精度的,...
  • 否则,如果任一操作数为浮点数,...
  • 否则,应在两个操作数上执行整数提升。
  • ...

积分促销在 4.5 (conv.prom/1) 中定义

如果 int 可以表示源类型的所有值,则 char、signed char、unsigned char、short int 或 unsigned short int 类型的右值可以转换为 int 类型的右值;否则,源右值可以转换为 unsigned int 类型的右值。

sizeof 的结果定义在 5.3.3 (expr.sizeof/6)

结果是 size_t 类型的常量

size_t 在 C 标准 (ISO 9899) 中定义,它是无符号整数类型

所以对于-1 > sizeof(int), > 触发通常的算术转换。通常的算术转换将 -1 转换为 unsigned int,因为 int 不能表示 的所有值size_t-1成为一个非常大的数字取决于平台。-1 > sizeof(int)也是如此true

于 2010-06-23T10:50:24.507 回答
14

因为无符号比有符号更强,并且 -1 转换为无符号值size_t,所以实际上-1 == 0xFFFFFFFF > 4

这就是它应该如何根据 C++ 标准工作

于 2010-06-23T09:19:26.247 回答
4

因为 -1 被强制转换size_t为无符号数据类型 - 所以(size_t)-1 == 4294967295(在 ​​32 位系统上)肯定大于 4

例如,如果您添加-Wall到 gcc 设置中,您会收到一条警告,提示您正在比较有符号和无符号数据类型

于 2010-06-23T09:51:31.957 回答
2

这很简单,也很悲伤。在 C/C++ 中:

  1. 大多数时候,无符号整数类型具有模整数的语义(它们代表等价类)
  2. 无符号整数类型的比较具有通常整数排序的语义,因此1U < 2U(IOW0U是最小值unsigned
  3. sizeof有类型size_t
  4. size_t是无符号整数类型
  5. 第 (1) 点暗示涉及有符号和无符号整数的混合算术计算是在无符号模算术中完成的:这是不违反“无符号平均模”规则的唯一可能性。将整数转换为与其等效的整数的等价类是微不足道的。(反之则需要选择一个整数来表示等价类。)
  6. -1 < 1U第 (5)点暗示unsigned(-1) < 1U, 和unsigned(-1)= - 1U, 显然- 1U < 1U, 所以-1 < 1U是真的。
  7. 点 (1,3,4) 暗示它sizeof something(主要)充当等效类(!!!)。
  8. 这一切都意味着-1 < sizeof something

结论:这是继承自 C 的设计错误。

规则:

仅将无符号类型用于模运算、位操作(&|^<<>>~运算符)、字节操作(unsigned char在 C/C++ 中表示“字节”)和字符(unsigned char在 C/C++ 中表示字符)。

不要使用无符号类型进行算术运算。

如果函数需要一个永远不应为负的整数值,则采用有符号整数,并可选择在函数中检查该值是否在范围内。

于 2011-12-09T04:57:50.180 回答