unsigned int与size_t

我注意到现代的C和C ++代码似乎几乎在任何地方都使用size_t来代替int / unsigned int – 从C字符串函数的参数到STL。 我很好奇这个原因和它带来的好处。

size_t类型是sizeof运算符(和offsetof运算符)的结果的无符号整数类型,因此保证足够大以包含系统可处理的最大对象的大小(例如,静态数组8GB)。

size_t类型可能大于,等于或小于unsigned int ,编译器可能会对此进行优化的假设。

您可以在C99标准第7.17节中找到更准确的信息,草案可以在互联网上以pdf格式获得,或者在C11标准第7.19节中找到,也可以作为pdf草案 。

Classic C(由Brian Kernighan和Dennis Ritchie在C Programming Language,Prentice-Hall,1978中描述的C的早期方言)没有提供size_t。 C标准委员会引入了size_t来消除可移植性问题

在embedded.com上详细解释(有一个很好的例子)

简而言之,size_t永远不会是负数,并且它最大限度地提高了性能,因为它被定义为无符号整数类型,它足够大,但不能太大,以表示目标平台上最大可能对象的大小。

大小不应该是负数,并且size_t实际上是一个无符号类型。 而且,由于size_t是无符号的,所以可以存储大约是相应的带符号类型的两倍的数字,因为我们可以使用符号位来表示幅度,就像无符号整数中的所有其他位一样。 当我们再增加一点的时候,我们就可以将我们可以表示的数字范围乘以两倍。

所以,你问,为什么不使用一个unsigned int ? 它可能无法保持足够的数量。 在unsigned int为32位的实现中,最大可以表示为4294967295 。 某些处理器(如IP16L32)可以复制大于4294967295字节的对象。

所以,你问,为什么不使用unsigned long int ? 它在一些平台上遇到了性能损失。 标准C要求long占用至少32位。 一个IP16L32平台将每个32位长度实现为一对16位字。 几乎所有这些平台上的32位操作符都需要两条指令(如果不是更多的话),因为它们在两个16位块中使用32位。 例如,移动32位长通常需要两个机器指令 – 一个移动每个16位块。

使用size_t可以避免这种性能损失。 根据这篇奇妙的文章 ,“Type size_t是一个typedef,它是一个无符号整数类型的别名,通常是无符号整数或无符号长整数,甚至可能是无符号长整数。每个标准C实现应该选择足够大的无符号整数, – 但不要大于需要 – 来表示目标平台上最大可能的对象的大小。“

size_t类型是sizeof运算符返回的类型。 它是一个无符号整数,能够表示主机支持的任何内存范围的字节大小。 它(通常)与ptrdiff_t相关,因为ptrdiff_t是一个有符号整数值,使得sizeof(ptrdiff_t)和sizeof(size_t)是相等的。

在编写C代码时,每当处理内存范围时都应该使用size_t。

另一方面,int类型基本上定义为主机可以用来最有效地执行整数运算的(带符号)整数值的大小。 例如,在许多较旧的PC型计算机上,sizeof(size_t)的值将是4(字节),而sizeof(int)的值将是2(byte)。 虽然CPU可以处理高达4 GiB的(逻辑)存储空间,但是16位算法比32位算法更快。

只有在关心效率时才使用int类型,因为它的实际精度很大程度上取决于编译器选项和机器体系结构。 特别是C标准规定了下面的不变式:sizeof(char)<= sizeof(short)<= sizeof(int)<= sizeof(long)对程序员可用的精度的实际表示没有其他限制,这些原始类型。

注意:这与Java中的不同(它实际上指定了每个类型'char','byte','short','int'和'long')的位精度。

类型size_t必须足够大以存储任何可能的对象的大小。 无符号整型不一定要满足这个条件。

例如,在64位系统中,int和unsigned int可以是32位宽,但是size_t必须足够大以存储大于4G的数字

在研究这个主题时,这个摘自glibc手册0.02也可能是相关的:

版本2.4之前的GCC的size_t类型和版本存在潜在的问题。 ANSI C要求size_t总是一个无符号类型。 为了与现有系统的头文件兼容,GCC将stddef.h' to be whatever type the system's size_t定义stddef.h' to be whatever type the system's sys / types.h定义的stddef.h' to be whatever type the system's 。 大多数在sys / types.h中定义size_t的Unix系统将其定义为一个签名类型。 库中的一些代码依赖于size_t是一个无符号类型,如果它被签名,将无法正常工作。

希望size_t是无符号的GNU C库代码是正确的。 size_t作为签名类型的定义是不正确的。 我们计划在2.4版本中,GCC总是将size_t定义为一个无符号类型, fixincludes' script will massage the system's sys / types.h',以免与此冲突。

同时,我们在编译GNU C库时,明确告诉GCC使用size_t的无符号类型来解决这个问题。 `configure'会自动检测GCC使用size_t的类型来安排覆盖它,如果有必要的话。

如果我的编译器设置为32位,那么size_t只不过是unsigned int的typedef。 如果我的编译器设置为64位,size_t只不过是unsigned long long的typedef。

size_t是指针的大小。

所以在32位或通用的ILP32(整数,长指针)模型size_t是32位。 并在64位或普通的LP64(长指针)模型size_t是64位(整数仍然是32位)。

还有其他的模型,但这些是g ++使用(至少默认)