什么是C中的size_t?
我在C中与size_t
混淆。我知道它是由sizeof
运算符返回的。 但究竟是什么呢? 这是一种数据类型吗?
假设我有一个for
循环:
for(i = 0; i < some_size; i++)
我应该用int i;
或size_t i;
?
维基百科 :
根据1999年的ISO C标准(C99),
size_t
是一个至少16位的无符号整数类型(见7.17和7.18.3节)。
size_t
是由几个C / C ++标准定义的无符号数据类型,例如在stddef.h
定义的C99 ISO / IEC 9899标准。 1可以通过包含stdlib.h
来进一步导入,因为这个文件在内部包含了stddef.h
。这个类型用来表示一个对象的大小。 采用或返回大小的库函数期望它们是类型的或具有
size_t
的返回类型。 此外,最经常使用的基于编译器的运算符sizeof应计算为与size_t
兼容的常量值。
作为一个暗示, size_t
是一个可以保存任何数组索引的类型。
size_t
是一个无符号类型。 所以它不能表示任何负值(<0)。 你在计算某些东西时使用它,并且确定它不能是负面的。 例如, strlen()
返回一个size_t
因为一个字符串的长度必须至少为0。
在你的例子中,如果你的循环索引将总是大于0,那么使用size_t
或其他任何未签名的数据类型可能是有意义的。
在使用size_t
对象时,必须确保在所有使用的上下文中(包括算术)都需要非负值。 例如,假设您有:
size_t s1 = strlen(str1); size_t s2 = strlen(str2);
你想找到str2
和str1
的长度的差异。 你不能这样做:
int diff = s2 - s1; /* bad */
这是因为分配给diff
的值始终是正数,即使在s2 < s1
时也是如此,因为计算是使用无符号类型完成的。 在这种情况下,取决于你的用例是什么,你可能会更好使用int
(或long long
) s1
和s2
。
在C / POSIX中有一些函数可以/应该使用size_t
,但不是因为历史原因。 例如, fgets
的第二个参数应该是size_t
,但是是int
。
size_t
是一个可以容纳任何数组索引的类型。
取决于实施,它可以是以下任何一种:
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
以下是我的机器的stddef.h
中如何定义size_t
:
typedef unsigned long size_t;
如果你是经验类型
echo | gcc -E -xc -include 'stddef.h' - | grep size_t
输出为Ubuntu 14.04 64位GCC 4.8:
typedef long unsigned int size_t;
请注意, stddef.h
由GCC提供,而不是在GCC 4.2的src/gcc/ginclude/stddef.h
下的glibc。
有趣的C99出场
-
malloc
将size_t
作为参数,所以它决定了可以分配的最大大小。由于它也是由
sizeof
返回的,我认为它限制了任何数组的最大大小。另请参阅: C中数组的最大大小
types.h的手册页说:
size_t应该是一个无符号整数类型
由于没有人提到它, size_t
的主要语言意义是sizeof
运算符返回该类型的值。 同样, ptrdiff_t
的主要意义在于从另一个指针中减去一个指针将产生该类型的值。 接受它的库函数是这样做的,因为它允许这样的函数在这些对象可能存在的系统上处理大小超过UINT_MAX的对象,而不会强制调用者浪费大于“unsigned int”值的代码就可以满足所有可能的目标。
size_t
和int
不可互换。 例如,在64位Linux上, size_t
是64位(即sizeof(void*)
),但是int
是32位。
还要注意size_t
是无符号的。 如果你需要签名的版本,那么在一些平台上有ssize_t
,这将与你的例子更相关。
作为一般规则,我会建议在大多数一般情况下使用int
,只有在有特定需求时(例如使用mmap()
才能使用size_t
/ ssize_t
。
一般来说,如果你从0开始向上,总是使用一个无符号类型来避免溢出,从而使你陷入一个负值的情况。 这是非常重要的,因为如果你的数组边界恰好小于你的循环的最大值,但是你的循环max恰好大于你的类型的最大值,那么你会绕过负数,并且你可能会遇到分段错误 (SIGSEGV )。 所以,一般来说,从不使用int作为从0开始并向上的循环。 使用无符号的。
size_t是无符号整数数据类型。 在使用GNU C库的系统上,这将是unsigned int或unsigned long int。 size_t通常用于数组索引和循环计数。
基本无符号整数类型之一的别名。
它是一种能够以字节表示任何对象大小的类型:size_t是sizeof运算符返回的类型,广泛用于标准库中以表示大小和计数。
根据我的理解, size_t
是一个unsigned
整数,它的位大小足以容纳本地体系结构的指针。
所以:
sizeof(size_t) >= sizeof(void*)