什么是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); 

你想找到str2str1的长度的差异。 你不能这样做:

 int diff = s2 - s1; /* bad */ 

这是因为分配给diff的值始终是正数,即使在s2 < s1时也是如此,因为计算是使用无符号类型完成的。 在这种情况下,取决于你的用例是什么,你可能会更好使用int (或long longs1s2

在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出场

  • mallocsize_t作为参数,所以它决定了可以分配的最大大小。

    由于它也是由sizeof返回的,我认为它限制了任何数组的最大大小。

    另请参阅: C中数组的最大大小

types.h的手册页说:

size_t应该是一个无符号整数类型

由于没有人提到它, size_t的主要语言意义是sizeof运算符返回该类型的值。 同样, ptrdiff_t的主要意义在于从另一个指针中减去一个指针将产生该类型的值。 接受它的库函数是这样做的,因为它允许这样的函数在这些对象可能存在的系统上处理大小超过UINT_MAX的对象,而不会强制调用者浪费大于“unsigned int”值的代码就可以满足所有可能的目标。

size_tint不可互换。 例如,在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*)