为什么size_t未签名?

Jon*_*Jon 56 c++ size-t unsigned-integer

Bjarne Stroustrup在C++编程语言中写道:

无符号整数类型非常适合将存储视为位数组的用途.使用无符号而不是int来再获得一位来表示正整数几乎不是一个好主意.通过声明无符号变量来确保某些值为正的尝试通常会被隐式转换规则所取代.

size_t似乎是无符号的"再获得一位代表正整数".那么这是一个错误(或权衡),如果是这样,我们应该在我们自己的代码中最小化它的使用吗?

Scott Meyers的另一篇相关文章就在这里.总而言之,他建议不要使用无符号in接口,无论值是否总是正数.换句话说,即使负值没有意义,也不一定要使用无符号.

Che*_*Alf 60

size_t 因历史原因未签名.

在具有16位指针的体系结构上,例如"小"模型DOS编程,将字符串限制为32 KB是不切实际的.

由于这个原因,C标准要求(通过所需范围)ptrdiff_t,有符号对应点size_t和指针差异的结果类型实际上是17位.

这些原因仍然适用于嵌入式编程领域的部分内容.

但是,它们不适用于现代32位或64位编程,其中一个更重要的考虑因素是C和C++的不幸隐式转换规则将无符号类型转换为bug吸引器,当它们用于数字时(和因此,算术运算和幅度比较).事后我们可以看到,20-20事后我们可以看到,采用这些特定转换规则的决定,例如string( "Hi" ).length() < -3实际上得到保证,是相当愚蠢和不切实际的.然而,这个决定意味着在现代编程中,对数字采用无符号类型具有严重的缺点并且没有优点 - 除了满足那些发现unsigned自我描述类型名称的人的感受,并且没有想到typedef int MyType.

总结一下,这不是一个错误.这是一个非常合理,实用的编程原因的决定.它与从Pascal到C++这样的边界检查语言转移期望无关(这是一个谬论,但非常常见,即使有些人从未听说过Pascal).

  • 所有好的编译器都会对`string("Hi").length()<-3`发出警告,但不会对两个signed int之间的比较进行比较; 如果`size_t`被定义为签名,你的生活将不会变得更容易,你只会犯下不同类型的错误. (13认同)
  • @Alex:我理解你的感受.然而,我们在保持C兼容性的同时在C++中进行强类型检查的原因是人类是错误的.当你能够做到这一点时,甚至还有一个众所周知的名称. (5认同)
  • 这在32位系统上也是一个非常大的问题.当你最多可以解决4GB时,你不希望被限制在2GB size_t. (5认同)
  • 我不同意"臭虫吸引者"部分.C(++)不是那种应该随意编写的语言,在阅读和理解关于语言或语言标准本身的详细书籍之前做出假设.我不认为无知是指责语言特征的有效借口.它就在那里,无论他们是否愿意,都必须处理它.关于C(++)和其他编程语言的更多内容已被破坏.以浮点为例.许多人开始使用它只有在正常数学中有效的各种假设.FP是个错误吗? (4认同)
  • @RustyX:这不是问题。使用 32 位带符号的 `ptrdiff_t` 仅排除大于 2GB 的单个 `char` 数组。当有人指出这一点时,有人说他们经常使用如此大的(相对于地址空间)`char` 数组。我不相信他们。无论如何,大多数 32 位 Windows 程序都被限制为 2GB。这在很长一段时间内运作良好。 (3认同)
  • 我看到 Java 犯了一个错误,不包括无符号类型,并且使解析 `0xffffffff` 或 `0xffffffffffffffff` 变得更难/更慢,或者在网络上使用无符号值。现在他们必须引入一些函数来支持 Java 8 的无符号操作。 (2认同)
  • @DanielH,在多少情况下,有人想要将 &gt;2 GB 的文件加载到一个 `char`s 数组中,然后坐在那里对其进行索引?相反,他们会不会使用流、指针或迭代器,或基于块的加载/处理,或者基本上除了数组索引之外的任何东西?请注意,我个人仍然不太相信 '_`unsigned` is bad_' 论点,但我也看不出你的论点是如何非常有用的反驳它。 (2认同)

gee*_*aur 26

size_tunsigned因为负面尺寸毫无意义.

(来自评论:)

它不是那么确保,而是说明是什么.你最后一次看到大小为-1的列表是什么时候?遵循该逻辑过多,您会发现根本不存在无符号,也不应允许位操作.- geekosaur

更重要的是:地址,你应该考虑的原因,没有签署.通过比较地址生成大小; 将地址视为已签名将完成错误的操作,并且对结果使用带符号的值会丢失数据,使得您对Stroustrup引用的读取显然认为是可接受的,但事实上并非如此.也许你可以解释负面地址应该做什么.- geekosaur

  • Stroustrup(和Meyer)的观点是,仅仅因为一个值永远不会是负数,并不意味着你应该使它无符号.例如,您不能再检测接口中传递的错误负值(隐式转换). (8认同)
  • 这不正是Stroustrup在编写"尝试通过声明无符号变量来确保某些值是正的时候"时所解决的问题吗? (7认同)
  • @NicolBolas:我的编译器没有给出警告:`size_t x = 0; for(size_t i = 10; i> = x; --i){}` - 你的吗? (7认同)
  • @Jon:警告让您知道存在运行时错误的可能性,应该修复.同样,如果你修复它(通过使函数采用带符号的int,或者通过确保不能传入负值),就没有问题了.如果你不修复它,如果你只是做一个演员来关闭编译器,那么你应该得到你得到的. (6认同)
  • 不应该是你的答案(size_t存在比较地址),而不是"负面大小没有意义"?后者似乎与Stroustrup和Meyers所说的相矛盾. (4认同)
  • *"遵循这个逻辑太过分了,你发现根本不存在无符号"* - 也许他们不应该,他们大多没用.至少,除非绝对必要,否则应该完全避免它们.这不是必要的情况.*"也不应允许位操作"* - 我不遵循你的逻辑. (4认同)
  • @Jon:"你再也找不到错误的负面价值"废话.C++规范可能会说转换很好,但任何有价值的编译器都会发出警告.如果你不解决它,不要向编译器抱怨你的搞砸了. (3认同)
  • 再次,请演示如何将其应用于机器地址,这是`size_t`为`unsigned`的根本原因. (2认同)
  • @Nicol,我说的是运行时错误。编译器无法检测到。(见迈耶斯链接) (2认同)
  • @geekosaur:按照这个答案的逻辑太过分了,你会得到"int dogs = 3;" vs"unsigned int dogs = 3;" 签名版本是错误的,因为负面的狗没有意义吗? (2认同)
  • Benjmin:"也许他们不应该......":至少java的作者似乎同意这一点.:) (2认同)
  • "_并不是那么确保,因为说明是什么."但是`sizeof`的东西不是**没有签名的.它是**正**整数.它有一个标志. (2认同)
  • 关于“对[比较地址]的结果使用有符号值将丢失数据”:从一个指针减去另一个指针的结果是“ptrdiff_t”类型,它*是*一种有符号整数类型。 (2认同)