size_t是否可移植?

9

GCC 4.4.1,C99

我正在使用 size_t ,而 size_t 是一个 unsigned int 。 然而,这取决于您是否运行在32位或64位上。

我将使用 size_t 来存储缓冲区的大小。

所以,如果在不同的体系结构之间使用,我认为这可能不太可移植。

只是一个问题,使用 size_t 在32位或64位上会引起什么情况下的严重问题?

7个回答

9
正如其他人所说,size_t 是正确的并且非常适合用于存储 sizeof() 的结果或任何可表示对象的大小(以字节为单位)。但是,您需要注意以下几点:
  1. size_t 与某些无符号整数类型的大小相同。它的字节数不一定与最大的无符号整数类型(例如 unsigned intunsigned long 等)相同。
  2. sizeof(size_t) 是一个实现定义的字节数,因此将其复制到任何整数类型中(除了 uintmax_t)或对其进行赋值是不明智的。我甚至不确定假设它与 uintmax_t 相等或更小是否安全。
  3. size_t 值写入二进制文件,然后通过另一个进程、在不同机器上或使用不同编译器选项编译的程序读回到 size_t 中可能会有危险。
  4. 在网络上传输 size_t 值,并尝试在另一端使用 sizeof(size_t) 缓冲区接收它是相当不安全的。
所有这些都是使用任何其他整数类型时的标准问题,除了 unsigned char 之外。因此,size_t 和任何其他整数类型一样具有可移植性。

8

size_t保证能够保存你的实现中任何对象的字节数。这就是为什么sizeof的返回类型是size_t

因此,它是可移植的。


13
只要你不试图把size_t类型变量保存到二进制文件或通过网络连接发送,它就是可移植的。一旦你开始这样做,它的可移植性就像被超级胶粘在地板上的非常不可移植的东西一样。 - user420442

3
在这种情况下,“便携式”具有多种不同的解释,很难确定您的意思。
“size_t”有一个非常特定的目的。它可以保存给定实现中任何对象的大小。也就是说,它是一种类型,可以始终接收“sizeof”运算符的结果。“size_t”没有其他用途,在其预期应用程序内部,它是100%可移植的,与任何东西一样便携。
您所询问的“便携式”是什么类型的,再次不清楚。

我正在使用size_t来获取缓冲区的大小。我正在进行一些套接字编程的消息传递,并且源代码将在Linux和Windows上编译。我需要获取从客户端发送的数据的size_t。谢谢。 - ant2009
@robUK,你应该在你的问题中添加这个重要的信息。 - quinmars

1

如果你正在使用malloc()或read(),那么使用size_t或ssize_t来表示缓冲区大小是有意义的。为了提高可移植性,可以使用SIZE_MAX、SSIZE_MAX、sizeof(type-in-your-buffer)和%zd或%zu printf()。


不幸的是,微软的 C 编译器不支持 printf() 函数中的 z 大小修饰符。 - Phil Miller
z修饰符是C99标准的一部分。迄今为止,Microsoft编译器使用的是C89/90。在C89/90中,必须手动实现size_t打印的“可移植性”。 - AnT stands with Russia
那些基础知识,我忘记了。嗯,他确实问过C99的问题。我想他真正关心的是“最严重”的问题,可能是Linux的乐观分配,或者轻率地假设(count*sizeof())不会溢出,或者认为你需要在第一次分配时就分配那么多内存。 - paul
微软自Visual Studio 2015起支持z长度修饰符,还支持其他一些长度修饰符。请参阅C Runtime (CRT) Features, Fixes, and Breaking Changes in Visual Studio 14 CTP1中的<stdio.h><conio.h>主题。 - MikeOnline

1

你还有off_t和ptrdiff_t/ssize_t,它们在不同架构之间也会有所不同。

如果你正确使用它们,它们就可以跨架构移植。在32位系统上,它们都将是32位宽度,而在64位系统上,它们都将是64位宽度。这正是你想要的 - 在32位系统上,缓冲区的大小不可能比32位size_t更大,但在64位系统上,它可以远远超过32位。

你永远不应该使用int、long或其他任何类型。除此之外,long的大小取决于平台(在大多数32位系统上为32位,在64位Unix系统上为64位,在64位Windows上为32位)。


0

这取决于您使用 size_t 的用途。

如果您将其用于确定内存缓冲区的大小,那么它是安全的,因为 size_t 足够大以寻址任何计算机的整个内存。因此,如果内存缓冲区大于该值,则无论如何都会出现问题。

另一方面,如果您将其用作通用的无符号整数来计算宇宙中星星的数量,例如,在 32 位系统上可能会出现问题(不确定 64 位系统是否有问题)。


1
不是这样的。size_t足以容纳实现支持的最大对象的大小。 size_t不足以寻址整个内存。对于后者,您需要使用intptr_t / uintptr_t - AnT stands with Russia
1
我承认我错了。但是,最大的对象可能是你在这种情况下需要的,否则你就有另一个问题。 - Jonatan

-2

唯一真正的严重问题是尝试访问相当大的数组或size_t的大数字。

就像普通的“int”在64位上可能足够,但在32位系统上因为它对于32位系统上的int来说太大而导致崩溃。


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