C语言 C 中的 size_t 是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2550774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is size_t in C?
提问by Vijay
I am getting confused with size_tin C. I know that it is returned by the sizeofoperator. But what exactly is it? Is it a data type?
我size_t对 C感到困惑。我知道它是由sizeof操作员返回的。但究竟是什么呢?它是一种数据类型吗?
Let's say I have a forloop:
假设我有一个for循环:
for(i = 0; i < some_size; i++)
Should I use int i;or size_t i;?
我应该使用int i;还是size_t i;?
采纳答案by sblom
According to the 1999 ISO C standard (C99),
size_tis an unsigned integer type of at least 16 bit (see sections 7.17 and 7.18.3).
size_tis an unsigned data type defined by several C/C++ standards, e.g. the C99 ISO/IEC 9899 standard, that is defined instddef.h.1It can be further imported by inclusion ofstdlib.has this file internally sub includesstddef.h.This type is used to represent the size of an object. Library functions that take or return sizes expect them to be of type or have the return type of
size_t. Further, the most frequently used compiler-based operator sizeof should evaluate to a constant value that is compatible withsize_t.
根据 1999 ISO C 标准 (C99),
size_t是至少 16 位的无符号整数类型(参见第 7.17 和 7.18.3 节)。
size_t是由多个 C/C++ 标准(例如 C99 ISO/IEC 9899 标准)定义的无符号数据类型,在stddef.h. 1它可以通过包含进一步导入,stdlib.h因为该文件在内部子包含stddef.h.此类型用于表示对象的大小。接受或返回大小的库函数期望它们的类型或返回类型为
size_t。此外,最常用的基于编译器的运算符 sizeof 应评估为与 兼容的常量值size_t。
As an implication, size_tis a type guaranteed to hold any array index.
作为暗示,size_t是一种保证保存任何数组索引的类型。
回答by Alok Singhal
size_tis an unsigned type. So, it cannot represent any negative values(<0). You use it when you are counting something, and are sure that it cannot be negative. For example, strlen()returns a size_tbecause the length of a string has to be at least 0.
size_t是无符号类型。因此,它不能表示任何负值(<0)。您在计算某物时使用它,并确定它不会为负数。例如,strlen()返回 asize_t因为字符串的长度必须至少为 0。
In your example, if your loop index is going to be always greater than 0, it might make sense to use size_t, or any other unsigned data type.
在您的示例中,如果您的循环索引将始终大于 0,则使用size_t或任何其他无符号数据类型可能是有意义的。
When you use a size_tobject, you have to make sure that in all the contexts it is used, including arithmetic, you want non-negative values. For example, let's say you have:
当您使用一个size_t对象时,您必须确保在使用它的所有上下文中,包括算术,您都需要非负值。例如,假设您有:
size_t s1 = strlen(str1);
size_t s2 = strlen(str2);
and you want to find the difference of the lengths of str2and str1. You cannot do:
你想找到的长度的差异str2和str1。你不能这样做:
int diff = s2 - s1; /* bad */
This is because the value assigned to diffis always going to be a positive number, even when s2 < s1, because the calculation is done with unsigned types. In this case, depending upon what your use case is, you might be better off using int(or long long) for s1and s2.
这是因为分配给的值diff始终为正数,即使在 时s2 < s1也是如此,因为计算是使用无符号类型完成的。在这种情况下,根据您的用例是什么,您最好使用int(或long long) fors1和s2。
There are some functions in C/POSIX that could/should use size_t, but don't because of historical reasons. For example, the second parameter to fgetsshould ideally be size_t, but is int.
C/POSIX 中有一些函数可以/应该使用size_t,但由于历史原因不要使用。例如,fgets理想情况下size_t,第二个参数 to应该是,但是是int。
回答by Arjun Sreedharan
size_tis a type that can hold any array index.
size_t是一种可以保存任何数组索引的类型。
Depending on the implementation, it can be any of:
根据实现,它可以是以下任何一种:
unsigned char
unsigned char
unsigned short
unsigned short
unsigned int
unsigned int
unsigned long
unsigned long
unsigned long long
unsigned long long
Here's how size_tis defined in stddef.hof my machine:
这size_t是在stddef.h我的机器中定义的方式:
typedef unsigned long size_t;
回答by codaddict
回答by supercat
Since nobody has yet mentioned it, the primary linguistic significance of size_tis that the sizeofoperator returns a value of that type. Likewise, the primary significance of ptrdiff_tis that subtracting one pointer from another will yield a value of that type. Library functions that accept it do so because it will allow such functions to work with objects whose size exceeds UINT_MAX on systems where such objects could exist, without forcing callers to waste code passing a value larger than "unsigned int" on systems where the larger type would suffice for all possible objects.
由于还没有人提到它,主要的语言意义size_t是sizeof运算符返回该类型的值。同样, 的主要意义ptrdiff_t在于从另一个指针中减去一个指针将产生该类型的值。接受它的库函数这样做是因为它允许这些函数在可能存在此类对象的系统上处理大小超过 UINT_MAX 的对象,而不会迫使调用者浪费代码在较大类型的系统上传递大于“unsigned int”的值对于所有可能的对象就足够了。
回答by Davislor
To go into why size_tneeded to exist and how we got here:
进入为什么size_t需要存在以及我们如何到达这里:
In pragmatic terms, size_tand ptrdiff_tare guaranteed to be 64 bits wide on a 64-bit implementation, 32 bits wide on a 32-bit implementation, and so on. They could not force any existing type to mean that, on every compiler, without breaking legacy code.
在实用方面,size_t并ptrdiff_t保证是64个位宽上的64位的实施方案中,32个比特宽上的32位实现,等等。在不破坏遗留代码的情况下,他们无法在每个编译器上强制任何现有类型。
A size_tor ptrdiff_tis not necessarily the same as an intptr_tor uintptr_t. They were different on certain architectures that were still in use when size_tand ptrdiff_twere added to the Standard in the late '80s, and becoming obsolete when C99 added many new types but not gone yet (such as 16-bit Windows). The x86 in 16-bit protected mode had a segmented memory where the largest possible array or structure could be only 65,536 bytes in size, but a farpointer needed to be 32 bits wide, wider than the registers. On those, intptr_twould have been 32 bits wide but size_tand ptrdiff_tcould be 16 bits wide and fit in a register. And who knew what kind of operating system might be written in the future? In theory, the i386 architecture offers a 32-bit segmentation model with 48-bit pointers that no operating system has ever actually used.
A size_torptrdiff_t不一定与intptr_tor相同uintptr_t。他们对仍然在使用的时候一定结构不同size_t而ptrdiff_t被添加到标准的80年代后期,并变得过时,当C99增加了许多新类型,但尚未消失(如16位Windows)。16 位保护模式下的 x86 有一个分段内存,其中最大的数组或结构的大小可能只有 65,536 字节,但far指针需要 32 位宽,比寄存器宽。在那些上,intptr_t本来是 32 位宽,但是size_t和ptrdiff_t可以是 16 位宽并适合寄存器。谁知道未来会写出什么样的操作系统?理论上,i386 架构提供了一个带有 48 位指针的 32 位分段模型,没有任何操作系统实际使用过。
The type of a memory offset could not be longbecause far too much legacy code assumes that longis exactly 32 bits wide. This assumption was even built into the UNIX and Windows APIs. Unfortunately, a lot of other legacy code also assumed that a longis wide enough to hold a pointer, a file offset, the number of seconds that have elapsed since 1970, and so on. POSIX now provides a standardized way to force the latter assumption to be true instead of the former, but neither is a portable assumption to make.
内存偏移的类型不可能是long因为太多的遗留代码假设long正好是 32 位宽。这种假设甚至内置于 UNIX 和 Windows API 中。不幸的是,许多其他遗留代码也假设 along的宽度足以容纳一个指针、一个文件偏移量、自 1970 年以来经过的秒数等等。POSIX 现在提供了一种标准化的方法来强制后一个假设为真,而不是前者,但两者都不是可移植的假设。
It couldn't be intbecause only a tiny handful of compilers in the '90s made int64 bits wide. Then they really got weird by keeping long32 bits wide. The next revision of the Standard declared it illegal for intto be wider than long, but intis still 32 bits wide on most 64-bit systems.
不可能是int因为 90 年代只有极少数编译器使用int64 位宽。然后他们通过保持long32 位宽而变得很奇怪。该标准的下一个修订版宣布int宽度大于是非法的long,但int在大多数 64 位系统上仍然是 32 位宽。
It couldn't be long long int, which anyway was added later, since that was created to be at least 64 bits wide even on 32-bit systems.
它不可能是long long int,无论如何都是后来添加的,因为即使在 32 位系统上,它也被创建为至少 64 位宽。
So, a new type was needed. Even if it weren't, all those other types meant something other than an offset within an array or object. And if there was one lesson from the fiasco of 32-to-64-bit migration, it was to be specific about what properties a type needed to have, and not use one that meant different things in different programs.
因此,需要一种新类型。即使不是,所有其他类型也意味着除了数组或对象内的偏移量之外的其他内容。如果从 32 位到 64 位迁移的惨败中得到一个教训,那就是具体说明一种类型需要具有哪些属性,而不是使用在不同程序中意味着不同事物的属性。
回答by dtoux
size_tand intare not interchangeable. For instance on 64-bit Linux size_tis 64-bit in size (i.e. sizeof(void*)) but intis 32-bit.
size_t并且int不可互换。例如,在 64 位 Linuxsize_t上,大小为 64 位(即sizeof(void*))但int为 32 位。
Also note that size_tis unsigned. If you need signed version then there is ssize_ton some platforms and it would be more relevant to your example.
另请注意,这size_t是未签名的。如果您需要签名版本,那么ssize_t在某些平台上有,它与您的示例更相关。
As a general rule I would suggest using intfor most general cases and only use size_t/ssize_twhen there is a specific need for it (with mmap()for example).
作为一般规则,我建议int在大多数一般情况下使用,并且仅在有特定需要时才使用size_t/ ssize_t(mmap()例如)。
回答by Mark
In general, if you are starting at 0 and going upward, always use an unsigned type to avoid an overflow taking you into a negative value situation. This is critically important, because if your array bounds happens to be less than the max of your loop, but your loop max happens to be greater than the max of your type, you will wrap around negative and you may experience a segmentation fault(SIGSEGV). So, in general, never use int for a loop starting at 0 and going upwards. Use an unsigned.
通常,如果您从 0 开始并向上移动,请始终使用无符号类型以避免溢出将您带入负值情况。这非常重要,因为如果您的数组边界恰好小于循环的最大值,但您的循环最大值恰好大于您的类型的最大值,您将环绕负数并且您可能会遇到分段错误(SIGSEGV )。因此,一般来说,永远不要将 int 用于从 0 开始并向上的循环。使用未签名。
回答by Prince
size_t is unsigned integer data type. On systems using the GNU C Library, this will be?unsigned?int?or?unsigned?long?int. size_t?is commonly used for array indexing and loop counting.
size_t 是无符号整数数据类型。在使用 GNU C 库的系统上,这将是?unsigned?int?or?unsigned?long?int。size_t? 通常用于数组索引和循环计数。
回答by bishwas pokharel
size_tor any unsigned type might be seen used as loop variable as loop variables are typically greater than or equal to 0.
size_t或任何无符号类型可能被视为循环变量,因为循环变量通常大于或等于 0。
When we use a size_tobject, we have to make sure that in all the contexts it is used, including arithmetic, we want only non-negative values. For instance, following program would definitely give the unexpected result:
当我们使用size_t对象时,我们必须确保在使用它的所有上下文中,包括算术,我们只需要非负值。例如,下面的程序肯定会给出意想不到的结果:
// C program to demonstrate that size_t or
// any unsigned int type should be used
// carefully when used in a loop
#include<stdio.h>
int main()
{
const size_t N = 10;
int a[N];
// This is fine
for (size_t n = 0; n < N; ++n)
a[n] = n;
// But reverse cycles are tricky for unsigned
// types as can lead to infinite loop
for (size_t n = N-1; n >= 0; --n)
printf("%d ", a[n]);
}
Output
Infinite loop and then segmentation fault

