在C语言中,size_t是什么?

808

我对C语言中的size_t感到困惑。我知道它是由sizeof运算符返回的。但它究竟是什么?它是一种数据类型吗?

假设我有一个for循环:

for(i = 0; i < some_size; i++)

我应该使用int i;还是size_t i;


18
如果这是你唯一的选项,那么如果 some_size 是有符号的,使用 int,如果它是无符号的,使用 size_t - Nate
10
@Nate,那是不正确的。POSIX有一个ssize_t类型,但实际上使用的正确类型是ptrdiff_t。 - Molly Stewart-Gallus
6
在《低级编程:C、汇编和Intel® 64上的程序执行》一书中,答案并不像那么清晰。正如该书所述,使用索引“int i”可能无法足够地寻址一个巨大的数组。因此,通过使用“size_t i”,您可以寻址更多的索引,因此即使您有一个巨大的数组,也不应该成为问题。“size_t”是一个数据类型:通常是“无符号长整型”,但这取决于您的系统。 - bruno
15个回答

4

size_t是无符号整数数据类型。在使用GNU C库的系统上,它将是unsigned int或unsigned long int。size_t通常用于数组索引和循环计数。


3

通常情况下,如果你从0开始递增,为了避免溢出导致负值情况的发生,应该使用无符号类型。这一点非常重要,因为如果你的数组边界小于循环的最大值,但是循环的最大值大于类型的最大值,那么你将会溢出并且可能会遇到分段错误(SIGSEGV)。因此,通常情况下,在从0开始递增的循环中永远不要使用int类型,而是使用无符号类型。


5
我无法接受你的论点。你认为溢出漏洞默默地导致访问数组中有效数据更好吗? - maf-soft
2
@maf-soft是正确的。如果错误未被检测到,那么它会比程序崩溃更糟糕。为什么这个答案会得到赞成? - yoyo_fun
如果它访问了您数组中的有效数据,那么这不是一个错误,因为无符号类型不会在有限制的情况下溢出,而有符号类型会。这个逻辑是什么意思呢?假设由于某种原因,您使用char来迭代256个元素的数组... 有符号类型将在第127个元素处溢出,并且第128个元素将导致sigsegv,但如果您使用无符号类型,则它将按预期遍历整个数组。然后再说,当您使用int时,您的数组实际上不会比20亿个元素更大,所以无论如何都没有关系... - Purple Ice
3
我无法想象任何情况下整数溢出都不是错误,无论是正数还是负数。仅仅因为你没有得到段错误并不意味着你看到了正确的行为!无论你的偏移量是正数还是负数,你都可能遇到分段错误或者没有遇到;这完全取决于你的内存布局。@PurpleIce,我认为你说的和这个答案不一样;你的论点似乎是你应该选择足够大的数据类型来容纳你想要放入其中的最大值,这只是纯粹的常识。 - Soren Bjornstad
1
话虽如此,从语义上讲,我更喜欢使用无符号类型作为循环索引;如果您的变量永远不会是负数,那么您最好在所选择的类型中表明这一点。这也可以让编译器发现值最终变成负数的错误,尽管至少在某些情况下,GCC非常糟糕地无法发现这个特定的错误(有一次我将一个无符号初始化为-1并没有收到警告)。同样,size_t对于数组索引在语义上是合适的。 - Soren Bjornstad

3

这是一个特定于平台的typedef。例如,在特定的机器上,它可能是unsigned intunsigned long。您应该使用此定义来使您的代码更具可移植性。


2

size_t或任何无符号类型可能被用作循环变量,因为循环变量通常大于或等于0。

当我们使用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

-4

据我理解,size_t是一个无符号整数,其位大小足以容纳本地架构的指针。

所以:

sizeof(size_t) >= sizeof(void*)

17
不正确。指针大小可以比 size_t 更大。例如:在 x86 实模式上的 C 编译器可以有 32 位的 FARHUGE 指针,但 size_t 仍然是 16 位。另一个例子:Watcom C 曾经使用特殊的 48 位宽度的“fat”指针来扩展内存,但 size_t 却没有。在具有哈佛体系结构的嵌入式控制器上,两者也没有关联,因为它们涉及不同的地址空间。 - Patrick Schlüter
1
在 https://dev59.com/OnI_5IYBdhLWcg3wAeA2 上,有更多关于AS/400使用128位指针和32位size_t的例子。 - Patrick Schlüter
2
这是彻头彻尾的谎言。不过,让我们把它留在这里。 - Antti Haapala -- Слава Україні

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