size_t是否总是无符号的?

70

问题:size_t类型始终是无符号的吗?例如,对于size_t x,是否始终有x > = 0


1
可能是一个重复问题 unsigned int vs. size_t - jww
如果你来到这里,很可能你正在寻找ptrdiff_t(或intrptr_t)。对于长度小于PTRDIFF_MAX的字符数组,std::ptrdiff_t充当了std::size_t的有符号对应类型:它可以存储任何类型的数组的大小,并且在大多数平台上,它与std::intptr_t同义。参见:https://dev59.com/PlsW5IYBdhLWcg3wXmO5 - Andrew
1
ssize_t 不是有符号的 size_t。它只能保证支持有符号值-1,虽然在Posix上可能有效,但在Windows上它是一个无符号类型。 - Dwedit
6个回答

57

是的。通常它被定义为类似下面这样的东西(在32位系统上):

typedef unsigned int size_t;

参考资料:

C++标准第18.1节定义了size_t位于<cstddef>中,该库在C标准中描述为<stddef.h>
C标准第4.1.5节将size_t定义为sizeof运算符结果的无符号整数类型。


嗯,我手头确实有C ++标准,但找不到它,可能是因为它实际上是在C(而不是C99)标准中定义的。我希望有人能找到它,因为我认为这是一个有趣的问题! - anon
@litb:是的。它并不可靠,但对于这种特定情况,我非常确定operator new使用size_t作为参数进行定义,因此它应该是无符号的。 - Mehrdad Afshari
2
感谢Mehrdad找到了这个参考资料。 - peterchen
12
请注意,在64位系统上,size_t通常是64位,而int仍可能是32位;这些都高度依赖于编译器。 - Christoph
2
@litb:C++2003,27.6.2.5.2定义了这些签名。请注意,第一个块是成员函数(因此不是第一个basic_ostream&参数),而最后一个块是自由函数。@Mehrdad:C++2003,5.3.4第10段:新表达式将请求的空间量作为类型为std::size_t的分配函数的第一个参数传递,与http://www.cplusplus.com/reference/std/new/operator%20new/中相同。 - David Rodríguez - dribeas
显示剩余6条评论

53
根据1999年的ISO C标准(C99),size_t是一个至少16位的无符号整数类型(见第7.17节和7.18.3节)。此标准还建议,如果可能的话,size_t不应该具有比long更大的整数转换级别,即如果遵循此建议,则将size_t强制转换为unsigned long就不会出现问题。1989年的ANSI C标准(ANSI C)没有提及最小大小或推荐的转换级别。1998年的ISO C++标准(C++98)(以及C++0x的当前草案)参考了C标准。第18.1节如下所述:

内容与标准的C库头文件<stddef.h>相同[...]


根据第1.2节,这意味着由1990年的ISO C标准(C90)定义的库,包括其1995年的第一次修订(C95):

ISO/IEC 9899:1990的第7条和ISO/IEC 9899/Amd.1:1995的第7条描述的库在此后称为标准C库


关于size_t的部分应继承自ANSI C:除了正文和节号之外,C90和ANSI C的标准相同。我需要一份规范修订副本才能确定stddef.h没有任何相关更改,但我怀疑这点。最小大小似乎是由stdint.h引入,即C99。请还考虑C++98第1.2节中的以下引用:

所有标准均可能进行修订, 并且基于本国际标准的协议方 被鼓励调查应用下面所指出的 最新版本的标准的可能性。


10
@Neil,他必须采用C标准,因为C++标准委派给它 :) 它本身不定义size_t :) (翻译:@Neil必须按照C标准来操作,因为C++标准将其委托给C标准。C++标准本身并没有定义size_t。) - Johannes Schaub - litb
2
是的,但C++标准没有引用C99标准。 - anon
1
我曾经认为C89/C95标准要求size_t至少为16位。但看起来只有C99有这个要求,而且至少为65535。 - Johannes Schaub - litb
2
它说它参考了C99,但对于库来说,它是指C90和C95。在1.2/2中,它说:“描述的库... C90和... C95在此后称为'Standard C Library'”。因此,当它指定cstddef的内容时,它是指C89(以及修正案C95,据我所知,这是C89的TC。就像C++03对C++98一样)(另一个时间由17.4.1.2/4指定)。 - Johannes Schaub - litb
@litb:你说得对,谢谢;我只是做了一个快速搜索,不知怎么找不到规范的参考资料;我会再编辑一些内容。 - Christoph
显示剩余3条评论

13

是的,size_t保证是无符号类型。


1
这不再被认为是一个好的回答。仅仅陈述事实并不是一个真正的回答,需要提供某种形式的理由或证明。 - Maarten Bodewes

6
根据标准,它是无符号的,但我记得一些旧实现在typedef中使用了有符号类型。从旧版GCC文档中可以看到:size_t类型和GCC 2.4之前的版本存在潜在问题。ANSI C要求size_t始终为无符号类型。为了与现有系统的头文件兼容,GCC将stddef.h中的size_t定义为系统sys/types.h定义的任何类型。大多数在sys/types.h中定义size_t的Unix系统将其定义为有符号类型。库中的某些代码依赖于size_t为无符号类型,并且如果它是有符号的,则无法正常工作。我不确定防范这种情况有多重要。我的代码假定它是无符号的。

我认为每个人都知道它很可能是无符号的,但除非有人能够引用相关的标准文档,否则我们永远不会确定。 - anon
目前我手头没有标准文档(虽然我相信所有相关的标准C90、C99以及C++98及以上版本都要求它是无符号类型),但是我想指出的是,无论标准如何,在某些特定情况下size_t可能是有符号类型,这是非常重要的例外。 - Michael Burr
现在已经有回答引用了C99来解决这个问题。但是,把这个答案留给那些遇到(旧)编译器/基本库意外问题的人可能是个好主意。 - Maarten Bodewes

3

size_t应该遵循C标准的相同定义,在C++标准的多个地方,它意味着它是无符号的自然数(特别是在分配器模板参数定义中)。

在C++标准的第18.1节(ISO/IEC 14882 - 第一版1998-01-01)中:

表15列出了已定义类型:ptrdiff_t和size_t

3 内容与标准C库头文件相同,但以下更改: 4 宏NULL在此国际标准中是一个实现定义的C++空指针常量(4.10)。

在此国际标准中,宏offsetof接受一组受限制的类型参数。类型应为POD结构或POD联合(第9条)。将offsetof宏应用于静态数据成员或函数成员字段的结果是未定义的。 另请参见:子句5.3.3,Sizeof,子句5.7,加法运算符,子句12.5,自由存储区以及ISO C子句7.1.6。


2

哦,这太糟糕了:

vector<MyObject> arr;
Fill(arr);
size_t size = arr.size();
for(size_t i = 1; i < size - 1; ++i)
{
  auto obj = arr[i];
  auto next = arr[i+1];
}

现在考虑 arr 为空的使用情形。


1
是的,但你能展示一下如何用惯用方式使上述代码正确吗? 严格来说,这不是对楼主问题的回答。 - user643011

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接