我注意到,现代C和c++代码似乎在几乎所有地方都使用size_t而不是int/unsigned int——从C字符串函数的参数到STL。我很好奇这样做的原因和它带来的好处。
当前回答
经典C语言(Brian Kernighan和Dennis Ritchie在《C编程语言》(Prentice-Hall, 1978)中描述的C语言的早期方言)没有提供size_t。C标准委员会引入size_t来消除可移植性问题
详见embedded.com(有一个很好的例子)
其他回答
这段摘自glibc手册0.02的摘录在研究这个主题时也可能是相关的:
在2.4版之前的GCC的size_t类型和版本中存在一个潜在的问题。ANSI C要求size_t始终是无符号类型。为了与现有系统的头文件兼容,GCC将stddef.h'中的size_t定义为系统的sys/types.h'所定义的类型。大多数Unix系统在`sys/types.h'中定义size_t,将其定义为有符号类型。库中的一些代码依赖于size_t是无符号类型,如果它是有符号类型,则不能正确工作。
希望size_t为unsigned的GNU C库代码是正确的。size_t作为有符号类型的定义是不正确的。我们计划在2.4版中,GCC将始终将size_t定义为无符号类型,fixincludes'脚本将修改系统的sys/types.h',以避免与此冲突。
与此同时,我们通过告诉GCC在编译GNU C库时显式地为size_t使用unsigned类型来解决这个问题。' configure'将自动检测GCC使用什么类型的size_t,如果需要,将重写它。
如果我的编译器被设置为32位,size_t就是unsigned int的typedef。如果我的编译器被设置为64位,size_t就是unsigned long long的typedef。
size_t类型是无符号整数类型,是sizeof操作符(和偏移操作符)的结果,因此它保证足够大,可以包含系统可以处理的最大对象的大小(例如,8Gb的静态数组)。
size_t类型可能大于、等于或小于unsigned int类型,编译器可能会对它进行优化假设。
您可以在C99标准第7.17节中找到更精确的信息,该标准草案可在Internet上以pdf格式提供,或者在C11标准第7.19节中也可以pdf格式提供。
经典C语言(Brian Kernighan和Dennis Ritchie在《C编程语言》(Prentice-Hall, 1978)中描述的C语言的早期方言)没有提供size_t。C标准委员会引入size_t来消除可移植性问题
详见embedded.com(有一个很好的例子)
简而言之,size_t从来不是负的,它最大限度地提高了性能,因为它被类型定义为无符号整数类型,该类型足够大(但不会太大),以表示目标平台上最大的可能对象的大小。
size永远不应该为负,size_t确实是一个无符号类型。同样,因为size_t是无符号的,所以可以存储大约是相应有符号类型中两倍大的数字,因为我们可以使用符号位来表示大小,就像无符号整数中的所有其他位一样。当我们再获得一位时,我们就将我们所能表示的数字的范围乘以大约2的因子。
那么,你会问,为什么不直接使用无符号整型呢?它可能无法容纳足够大的数字。在unsigned int为32位的实现中,它所能表示的最大数字是4294967295。有些处理器(如IP16L32)可以复制大于4294967295字节的对象。
你会问,为什么不用unsigned long int呢?在某些平台上,这会造成性能损失。标准C要求long至少占用32位。IP16L32平台将每个32位长实现为一对16位字。在这些平台上,几乎所有32位操作符都需要两条指令,如果不是更多的话,因为它们在两个16位块中处理32位。例如,移动一个32位长的数据块通常需要两条机器指令——一条用于移动每个16位的数据块。
使用size_t可以避免这种性能损失。根据这篇精彩的文章,“size_t类型是一个类型定义,它是一些无符号整数类型的别名,通常是unsigned int或unsigned long,但也可能是unsigned long long。每个标准C实现都应该选择足够大的无符号整数,但不能超过所需的大小,以表示目标平台上可能存在的最大对象的大小。”
推荐文章
- 如何构建和使用谷歌TensorFlow c++ api
- C“int”的大小是2字节还是4字节?
- 多维数组如何在内存中格式化?
- printf()和puts()在C语言中的区别是什么?
- 断言是邪恶的吗?
- 下面这些短语在c++中是什么意思:0 -,default-和value-initialization?
- 在STL地图中,使用map::insert比[]更好吗?
- C++ Linux的想法?
- 有效,但毫无价值的语法在开关情况下?
- 如何为Fedora安装g++ ?
- Std::cin输入空格?
- c++标准是否要求iostreams的性能很差,或者我只是在处理一个糟糕的实现?
- 有一个好的Valgrind Windows的替代品吗?
- gcc在哪里查找C和c++头文件?
- 为什么我们需要require require ?