【问题标题】:How to detect negative number assigned to size_t?如何检测分配给 size_t 的负数?
【发布时间】:2013-03-20 13:22:55
【问题描述】:

此声明在 g++ -pedantic -Wall(版本 4.6.3)中编译时没有警告:

std::size_t foo = -42;

不那么明显的虚假是声明一个带有 size_t 参数的函数,并用一个负值调用它。这样的函数能否防止无意的否定论点(显示为无数个 quintillion,遵守 §4.7/2)?

不完整的答案:

只是将 size_t 更改为 (signed) long 会丢弃 size_t 的语义和其他优点。

将其更改为 ssize_t 只是 POSIX,而不是标准。

将其更改为 ptrdiff_t 很脆弱,有时会损坏。

测试大值(高位设置等)是任意的。

【问题讨论】:

  • +1 表示“无数个 quintillion”。 Jk,+1,因为这是个好问题。
  • 谢谢你,哈莱克斯。我只是从那里引用了标准。
  • 测试高位不是随意的,是标准的。
  • IMO unsigned 是邪恶的。我见过由while(size_t index < container.size()-1) 之类的东西在空container 上触发引起的可怕错误。我知道unsigned 类型有时在可用位很少时可能很有用,但是将广泛使用的通用整数类型size_t 定义为unsigned 而不是int 是一个巨大的可怕的巨大错误。抱歉漫无边际,这恰好是我的一个小烦恼。 unsigned ...呃。

标签: c++ signed size-t


【解决方案1】:

为此发出警告的问题在于,根据标准,它不是未定义的行为。如果您将有符号值转换为相同大小的无符号类型,您可以稍后将其转换回有符号值并在任何符合标准的编译器上获取原始值。

此外,对于各种错误情况,使用转换为 size_t 的负值是相当常见的做法——许多系统调用成功返回无符号(size_toff_t)值或返回 -1(转换为无符号)一个错误。因此,向编译器添加这样的警告会导致许多现有代码出现虚假警告。 POSIX 尝试将其编码为 ssize_t,但这会中断可能成功的调用,其返回值大于 ssize_t 的最大有符号值。

【讨论】:

  • 运行时检测是一个比编译器警告更大的问题。但是你给了我一个想法,在函数内部,将值转换回签名并测试
  • @CamilleGoudeseune D'oh,转换回签名和测试 LONG_MAX 或std::numeric_limits< long >::max(),并将无符号值与该值进行比较,不进行类型转换。
  • @hvd:重点是规范确实允许使用相同大小的有符号和无符号类型来回转换,并获得相同的值,即使范围不同。
  • @hvd:但是您正在从具有 65535 值的类型转换为具有 65536 的类型,然后再转换回具有 65535 的类型。没有问题。
  • @ChrisDodd 哦,你是对的,我误读了你的说法。在那种情况下,我必须同意你是正确的,没有技术原因是不可能的。不幸的是,即使有可能,它仍然不是标准所说的。 (稍后会更详细地评论。)
【解决方案2】:

以下摘自私人图书馆。

#include <limits.h>

#if __STDC__ == 1 && __STDC_VERSION__ >= 199901L || \
    defined __GNUC__ || defined _MSC_VER
    /* Has long long. */
    #ifdef __GNUC__
        #define CORE_1ULL __extension__ 1ULL
    #else
        #define CORE_1ULL 1ULL
    #endif
    #define CORE_IS_POS(x) ((x) && ((x) & CORE_1ULL << (sizeof (x)*CHAR_BIT - 1)) == 0)
    #define CORE_IS_NEG(x) (((x) & CORE_1ULL << (sizeof (x)*CHAR_BIT - 1)) != 0)
#else
    #define CORE_IS_POS(x) ((x) && ((x) & 1UL << (sizeof (x)*CHAR_BIT - 1)) == 0)
    #define CORE_IS_NEG(x) (((x) & 1UL << (sizeof (x)*CHAR_BIT - 1)) != 0)
#endif

#define CORE_IS_ZPOS(x) (!(x) || CORE_IS_POS(x))
#define CORE_IS_ZNEG(x) (!(x) || CORE_IS_NEG(x))

这应该适用于所有无符号类型。

【讨论】:

  • 很好地使用了 CHAR_BIT,stackoverflow.com/a/3200969/2097284。但是什么隐式转换使这项工作有效? (x) &amp; ... 将 x 转换为 ULL? (x) &amp;&amp; 是指(x != 0) &amp;&amp;?而 ZPOS 的意思是&gt;= 0 ?
  • 是的,IS_POS/IS_NEG 测试&gt; 0&lt; 0;和IS_ZPOS/IS_ZNEG 测试&gt;= 0&lt;= 0。不涉及演员;宏仅使用可用于构造位掩码表达式(因此 UL 和 ULL)的最大无符号整数类型测试最高位((x) &amp; ... 部分)。 (x) &amp;&amp; ... 部分仅表示 (x) != 0
猜你喜欢
  • 2019-10-07
  • 1970-01-01
  • 2011-09-02
  • 2021-01-24
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 2017-05-14
相关资源
最近更新 更多