无符号整数与size_t
我注意到,现代C和C ++代码似乎在从C字符串函数的参数到STL的几乎所有地方都使用size_t而不是int / unsigned int。我对此的原因及其带来的好处感到好奇。
解决方案
size_t类型是无符号整数类型,它是sizeof运算符(和offsetof运算符)的结果,因此保证它足够大,可以容纳系统可以处理的最大对象的大小(例如8Gb的静态阵列)。
size_t类型可以大于,等于或者小于unsigned int类型,并且编译器可能会对其进行假设以进行优化。
我们可以在C99标准的第7.17节中找到更精确的信息,该草案的草案以pdf格式在Internet上提供,或者在C11标准的第7.19节中也以pdf草案的形式提供。
类型size_t必须足够大以存储任何可能的对象的大小。 Unsigned int不必满足该条件。
例如,在64位系统中,int和unsigned int可能为32位宽,但是size_t必须足够大以存储大于4G的数字
Classic C(由Brian Kernighan和Dennis Ritchie在1978年Prentice-Hall的C编程语言中描述的C的早期方言)没有提供" size_t"。 C标准委员会引入了" size_t"以消除可移植性问题
在Embedded.com上进行了详细说明(有一个很好的例子)
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(字节)。尽管CPU可以处理多达4 GiB的(逻辑)存储空间,但16位算术比32位算术快。
仅在关心效率时才使用int类型,因为它的实际精度在很大程度上取决于编译器选项和计算机体系结构。特别是C标准指定了以下不变量:sizeof(char)<= sizeof(short)<= sizeof(int)<= sizeof(long)对每个程序的实际精度表示没有其他限制这些原始类型。
注意:这与Java中的不同(Java实际上为Java的" char"," byte"," short"," int"和" long"类型指定了位精度)。
size_t是指针的大小。
因此,在32位或者普通ILP32(整数,长整数,指针)模型中,size_t为32位。
并以64位或者通用LP64(长指针)模型size_t为64位(整数仍为32位)。
还有其他模型,但是这些是g ++使用的模型(至少默认情况下)
简而言之,`size_t'永远不会为负,它会最大化性能,因为它的typedef值是足够大(但又不太大)的无符号整数类型,可以表示目标平台上最大可能对象的大小。
大小永远不能为负数,并且size_t
实际上是一个无符号类型。同样,因为size_t
是无符号的,所以我们可以存储的数字大约是相应有符号类型的两倍,因为我们可以像无符号整数中的所有其他位一样,使用符号位来表示幅度。当再获得一位时,我们将可以表示的数字范围乘以大约2的倍数。
所以,你问,为什么不只使用一个unsigned int
?它可能无法容纳足够大的数字。在" unsigned int"是32位的实现中,它可以表示的最大数字是" 4294967295"。一些处理器,例如IP16L32,可以复制大于" 4294967295"字节的对象。
那么,我们问,为什么不使用unsigned long int
?它会在某些平台上造成性能损失。标准C要求'long'至少占用32位。 IP16L32平台将每个32位长实现为一对16位字。在这些平台上,几乎所有32位运算符都需要两条指令(即使不是更多指令),因为它们在两个16位块中使用32位。例如,移动32位长通常需要两个机器指令-一个移动每个16位块。
使用size_t
避免了这种性能损失。根据这篇精彩的文章," size_t类型是一个typedef,它是某些无符号整数类型的别名,通常是unsigned int或者unsigned long,甚至可能是unsigned long long。每个标准C实现都应选择足够大但不超过所需数量的无符号整数,以表示目标平台上最大可能对象的大小。"