size_t和unsigned int有什么区别?

148

我对 size_t 非常困惑。在互联网上搜索后,无论何处都提到 size_t 是一种无符号类型,因此只能表示非负值。

我的第一个问题是:如果它仅用于表示非负值,为什么我们不使用 unsigned int 而是使用 size_t

我的第二个问题是: size_tunsigned int 可互换吗?如果不能,那么为什么?

还有人能否给我一个好的 size_t 的例子,并简要解释其工作原理?


7
typedef /此部分依赖于实现/ size_t; - P0W
5
可能是unsigned int vs. size_t的重复问题。 - user146043
7个回答

120
如果它用于表示非负值,那么为什么我们不使用unsigned int而是size_t呢?
因为unsigned int并不是唯一的无符号整数类型。根据实现,size_t可以是任何unsigned charunsigned shortunsigned intunsigned longunsigned long long
第二个问题是size_tunsigned int是否可以互换,如果不能,那么为什么?
它们不能互换,原因如上所述^^
还有人能给我一个关于size_t的好例子和简要工作原理吗?

我不太明白你所说的“其简短工作”是什么意思。它的工作方式与任何其他未签名类型相同(特别是,与其类型定义为的类型相同)。当您描述对象的大小时,建议使用size_t。特别是,sizeof运算符和各种标准库函数(例如strlen())返回size_t

额外福利:这里有一篇好文章关于size_t(以及密切相关的ptrdiff_t类型)。它很好地解释了为什么应该使用它。


1
size_t怎么可能是unsigned char?这在标准中被允许吗?我的意思是,如果是这样的话,任何人都如何能够使用calloc()(以及相关函数)、strlen()等?这对我来说似乎是荒谬的。 - Pryftan
1
我认为size_t在标准中被定义为“无符号整数类型”,但不要求它与任何unsigned {char, short, int, long, long long}相同。 - Paul Hankin
@Pryftan,例如,一个8位架构会使用unsigned char作为size_t。你不需要担心size_t会是什么,编译器会根据目标架构来处理它。 - Ekrem Dinçel
“size_t的内存大小(以字节为单位)由编译器决定。编译器(以某种方式)确定最适合的无符号整数数据类型,可以容纳体系结构/硬件支持的最大可能数组大小(1个字节/最小的内存单元),并将其typedef为size_t” - 请验证我的陈述是否正确。 - user15933960

113

C语言中有5种标准的无符号整数类型:

  • unsigned char(无符号字符型)
  • unsigned short(无符号短整型)
  • unsigned int(无符号整型)
  • unsigned long(无符号长整型)
  • unsigned long long(无符号长长整型)

它们的大小和范围各异(简单来说,每个类型的范围都是下一个类型范围的子集,但其中一些类型的范围可能相同)。

size_t 是一个typedef(即别名),代表了某个无符号类型(可能是上述某个类型或扩展的无符号整数类型,但这不太可能)。它是由sizeof运算符得出的类型。

在某个系统上,使用 unsigned int 来表示大小可能是最合适的;在另一个系统上,使用 unsigned longunsigned long long 可能更合适。(但size_t 不太可能是 unsigned charunsigned short,但也是允许的。)

size_t 的目的是为了让程序员不必担心使用哪种预定义类型来表示大小。

假设sizeof产生的是unsigned int的代码将不可移植。而假设它产生的是size_t的代码更可能是可移植的。


8
我认为这应该是被采纳的答案,因为它解释了为什么应该使用 size_t。 - kuchi
@keith-thompson 这是否意味着 size_t 对应的具体类型(例如 unsigned intunsigned long 等)取决于运行代码的机器?也就是说,在一种机器架构上,它对应于 unsigned int,但在另一种架构上,它将对应于 unsigned long 等等? - Richie Thomas
1
@RichieThomas:这取决于C语言的实现。在同一架构上,两个不同的编译器可能会为size_t选择不同的类型,特别是如果例如unsigned longunsigned long long大小相同。 - Keith Thompson
@Pryftan:“系统”或“字长”的含义并不是完全清楚的。例如,在完全相同的硬件上,Windows实现通常具有32位的“long”,而类Unix(包括基于Linux的)实现通常具有64位的“long”。x86-64(x64)系统的字长为64位,但“int”几乎总是32位。所有这些选择最终取决于C语言实现,特别是编译器。编译器的选择可能会受到ABI的指导。 - Keith Thompson
1
@Pryftan 请看一下 Motorola 68000 系列,还有早期的 Intel x86 系列(回溯到 8086 和 8088)。 - Keith Thompson
显示剩余4条评论

12

size_t有一个特定的限制。

引用自http://www.cplusplus.com/reference/cstring/size_t/

是一个基本无符号整数类型的别名。

它是一种能够以字节为单位表示任何对象大小的类型:size_t是sizeof运算符返回的类型,广泛用于标准库中表示大小和计数。

它不能与unsigned int互换,因为int的大小由数据模型指定。例如,LLP64使用32位int,而ILP64使用64位int


6
那句引语出自哪里?(它不是来自C标准。) - Keith Thompson
4
问题标记为 [tag:c]。C++ 标准对 C 没有影响。 - IInspectable

11

除了其他答案之外,它还记录了代码并告诉人们您正在谈论对象在内存中的大小。


好的观点。一个 apple 是一个 _apple_,一个 size_t 是一个 size... - dom_beau

7

size_t被用来存储数据对象的大小,并且能够保证存储任何特定C实现所创建的数据对象的大小。这种数据类型可能比unsigned int类型更小(以位数计算),更大或者恰好相同。


2

简单来说,size_t是与平台和实现相关的,而unsigned int仅与平台有关。

"最初的回答"的原意是Original Answer。


2

size_t类型是C/C++语言中的一种基本无符号整数类型,是sizeof运算符返回结果的类型。该类型的大小被选择为能够存储任何类型的理论可能的最大数组大小。在32位系统上,size_t将占用32位,在64位系统上将占用64位。换句话说,size_t类型的变量可以安全地存储指针。唯一的例外是指向类函数的指针,但这是一个特殊情况。虽然size_t可以存储指针,但最好使用另一种无符号整数类型uintptr_t来实现(其名称反映了它的功能)。类型size_t和uintptr_t是同义词。通常使用size_t类型作为循环计数器、数组索引和地址运算。size_t类型的最大可能值是常量SIZE_MAX。


2
size_t 可以存储任何单个对象的大小。指针可以指向任何对象的任何字节。例如,您可以拥有一个具有 64 位地址空间的系统,它将任一对象的大小限制为 2**32-1 字节。不能保证 size_tuintptr_t 是相同类型。 - Keith Thompson

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