我该在哪里找到size_t的定义?

147

我看到了使用此类型定义的变量,但我不知道它来自哪里,也不知道它的目的是什么。为什么不使用 int 或 unsigned int?(其他“相似”的类型如何?void_t等)。


1
什么是 C 语言中 size_t 和 int 的区别? - kjfletch
参见https://dev59.com/R3NA5IYBdhLWcg3wHp6B#1089204 - Christoph
在最简单的程序中,如果没有“偶然”加载size_t定义,但我仍然需要在某些上下文中使用它(例如访问std::vector<double>),那么我会使用上下文来提取正确的类型。例如,typedef std::vector<double>::size_type size_t - alfC
10
OP明确要求:“我在哪里可以找到size_t的定义?” 我也因为同样的问题来到这里。引用的重复帖子并没有讨论在哪里找到声明。 - jww
11
这个问题显然不同于链接的那个问题。 “我在哪里找到某物”与“有什么区别”不同(即使一个问题的答案提供了另一个问题的答案)。 我在Google上搜索“c ++ where is size_t definition”,直接将我带到了这里,如果因为这是不同的,我会错过其他问题。 - Dan Nissenbaum
9个回答

142

来源:维基百科

stdlib.hstddef.h头文件定义了一个叫做size_t的数据类型1,用于表示对象的大小。使用该数据类型作为参数的库函数希望其是size_t类型,并且sizeof运算符所得到的结果也是size_t类型。

size_t的实际类型取决于平台;一个常见的错误是假定size_t与无符号整数相同,这可能导致编程错误2,尤其是在64位架构变得更加普遍的情况下。

来源:C99 7.17.1/2

标准头文件stddef.h中定义了以下类型和宏

<snip>

size_t

sizeof运算符结果的无符号整数类型


3
例如,在Win64系统中,intunsigned int类型是32位的,而size_t类型是64位的。 - Michael Burr
7
请参考ISO C(99)标准(C++标准也包含在内)的第7.17和7.18.3节。 - Martin York
3
为什么不直接编辑答案呢?既然你知道标准中写在哪里。 - Hi-Angel
1
那么C++的答案在哪里呢? - Lothar
@Lothar 我认为唯一的区别是 size_t 可能是一个关键字,否则具有相同的含义。 - Paul Stelian

44
根据 en.cppreference.com上的size_t说明size_t定义在以下头文件中:
std::size_t

...    

Defined in header <cstddef>         
Defined in header <cstdio>      
Defined in header <cstring>         
Defined in header <ctime>       
Defined in header <cwchar>

4
这正是我所需要的,这个答案应该得到点赞。 - neodelphi
std::size_t 定义在头文件 <cstddef> 中,符合 ISO C++ 标准,并且被其他列出的头文件使用。 - fpmurphy

28

size_t是sizeof运算符(ISO C99第7.17节)结果的无符号整数类型。

sizeof运算符产生其操作数的大小(以字节为单位),该操作数可以是表达式或类型的括号名称。大小从操作数的类型确定。结果是一个整数。结果的值是实现定义的,其类型(一种无符号整数类型)为size_t(ISO C99第6.5.3.4节)。

IEEE Std 1003.1-2017(POSIX.1)指定size_t在头文件sys/types.h中定义,而ISO C则指定头文件stddef.h。在ISO C++中,类型std::size_t在标准头文件cstddef中定义。


最佳答案是引用标准的答案。 - Martin York
1
@Martin - 确实如此,但我认为问题中“为什么不使用unsigned int”部分与“size_t是什么”部分一样有趣(或更有趣),而您在标准中找不到这一点。 - Michael Burr
是的,除了没有“第17.17节”:p。这很罕见,没有人提到Void_t。 - Eliseo Ocampos
我接受这个答案,因为它直接回答了问题,但如果能与Michael的答案相辅相成就更好了。 - Eliseo Ocampos
65
很遗憾,您的回答没有告诉我需要包含哪个头文件。 - hookenz

6
实际上,size_t 表示您可以寻址的字节数。在过去的 10-15 年中,大多数现代架构都是 32 位,这也是无符号整数的大小。然而,我们正在向 64 位寻址转移,而 uint 很可能仍然保持在 32 位(它的大小在 C++ 标准中没有保证)。为了使依赖于内存大小的代码跨架构可移植,应该使用 size_t。例如,像数组大小这样的东西应该始终使用 size_t。如果查看标准容器,::size() 总是返回一个 size_t
另外请注意,Visual Studio 有一个编译选项,可以检查此类错误,名为“检测 64 位可移植性问题”。

2
这样你总是知道尺寸大小,因为有一个特定的类型专门用于大小。这个问题本身就说明了它可能是一个问题:是一个int还是unsigned int?此外,大小是多少(shortintlong等)?
因为分配了一个特定的类型,所以你不必担心长度或符号。
实际定义可以在C++参考库中找到,其中写着:
类型:size_t(无符号整型)
头文件:<cstring> size_t 对应于语言运算符 sizeof 返回的整数数据类型,并在 <cstring> 头文件(以及其他头文件)中定义为无符号整型。
<cstring> 中,它被用作函数 memchrmemcmpmemcpymemmovememsetstrncatstrncmpstrncpystrxfrm 中参数 num 的类型,在所有这些情况下,它都被用来指定函数需要影响的最大字节数或字符数。
它还被用作 strcspnstrlenstrspnstrxfrm 的返回类型,用于返回大小和长度。

2

size_t 应该在标准库的头文件中定义。根据我的经验,它通常只是 unsigned int 的 typedef。但重点是,它不一定非得这样。 像 size_t 这样的类型允许标准库供应商在适合平台的情况下更改其底层数据类型。如果您通过强制转换等方式假设 size_t 始终是 unsigned int,那么如果您的供应商将 size_t 更改为例如 64 位类型,则未来可能会遇到问题。出于这个原因,假设任何关于此或任何其他库类型的事情都是危险的。


1

我对void_t不太熟悉,只是通过谷歌搜索了解到它(它在AT&T研究中心的Kiem-Phong Vo编写的vmalloc中使用 - 我相信它也被用在其他库中)。

各种xxx_t typedef用于从特定的具体实现中抽象出类型,因为用于某些事物的具体类型可能因平台而异。例如:

  • size_t抽象出用于保存对象大小的类型,因为在某些系统上,这将是32位值,而在其他系统上可能是16位或64位。
  • Void_t抽象出由vmalloc库例程返回的指针类型,因为它是为在ANSI/ISO C之前编写的系统上工作而编写的,其中void关键字可能不存在。至少我是这么猜的。
  • wchar_t抽象出用于宽字符的类型,因为在某些系统上,它将是16位类型,而在其他系统上,它将是32位类型。

因此,如果您编写宽字符处理代码使用类型而不是例如<无符号短整型>,那么这段代码将更具可移植性,可以在各种平台上运行。


这正是我在寻找的,部分地。正如我在fpmurphy的回答中所说的评论,如果能够与这个答案相辅相成就更好了(如果您不介意,也许您可以编辑一下) :) - Eliseo Ocampos

1
在极简程序中,如果没有“偶然”加载size_t定义但我仍需要在某些上下文中使用它(例如访问std::vector<double>),那么我会使用上下文来提取正确的类型。例如:typedef std::vector<double>::size_type size_t。(如果需要限制范围,请用namespace {...}括起来。)

1
关于“为什么不使用int或unsigned int?”,简单来说是因为语义上更有意义。当然,实际原因是它可以被定义为int,然后稍后升级为long,而无需更改任何人的代码,但更根本的原因是类型应该是有意义的。简化一下,size_t类型的变量适合用于包含大小,就像time_t类型适合用于包含时间值一样。如何实现这些应该是实现工作的职责。与将所有内容都称为int相比,使用这样有意义的类型名称有助于澄清程序的含义和意图,就像任何丰富的类型集一样。

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