使用 ssize_t 与 int
Posted
技术标签:
【中文标题】使用 ssize_t 与 int【英文标题】:Using ssize_t vs int 【发布时间】:2013-10-14 00:22:28 【问题描述】:代码
我有一个函数,我可以用 一种 四种可能的方式编写它:
int do_or_die(int retval);
int do_or_die(ssize_t retval);
ssize_t do_or_die(int retval);
ssize_t do_or_die(ssize_t retval);
然后它会被两种库函数调用:
written = do_or_die(write(...)); // POSIX write returns ssize_t
printed = do_or_die(printf(...)); // printf returns int
问题
我应该使用哪个原型? 我应该给written
和printed
提供什么类型?
我希望拥有最强大和最标准的代码,同时仍然只有一个 do_or_die
函数。
在这种情况下我使用的是 C99,但如果 C11 的答案不同,那么我也想知道这一点,以备将来使用。
【问题讨论】:
由于ssize_t
可能比int
更宽,您可能应该使用第四个原型。
@PaulR 是否有保证,或者int
也可能比ssize_t
更宽?
@delnan:我不认为这是可能的,尽管他们可能是平等的。
@PaulR 好吧,我可以想象一个 int 更宽的体系结构:分段内存是 16 位 x86(所以 ssize_t 是 16 位),具有 32 位整数。问题实际上是相关标准(某些版本的 C,在本例中为 POSIX)是否能保证任何事情。
感谢大家的洞察!我认为在实际代码中我会执行int do_or_die(intmax_t retval);
,如果它不适合则直接退出,因为由于系统的某些物理限制,不适合int
的返回值纯粹是理论上的。
【参考方案1】:
POSIX 标准不能保证sizeof(int) >= sizeof(ssize_t)
,反之亦然。通常ssize_t
大于int
,但C99 中安全且可移植的选项是使用intmax_t
代替参数和返回值。
您拥有 wrt 的唯一保证。 int
和ssize_t
之间的关系是:
int
可以根据 ISO C 存储至少 [-2^15 ... 2^15-1] 范围内的值
ssize_t
可以根据 POSIX 存储至少 [-1 ... 2^15-1] 范围内的值(请参阅 _POSIX_SSIZE_MAX
)。
(有趣的是,甚至不能保证ssize_t
可以存储其正数范围的负数。它不是带符号的size_t
,而是带有错误值的“大小类型”。)
【讨论】:
ssize_t
实际上在 C 标准中根本没有指定。它是 POSIX 标准的一部分。
ssize_t 的链接只提到了最大尺寸,仅此而已,甚至没有提到签名。你能提供一个参考吗?谢谢。
我刚刚发现 int_fast64_t
存在于 C++11 中。我很想将它用作我的默认整数类型“最快的有符号整数类型,宽度分别至少为 8、16、32 和 64 位”en.cppreference.com/w/cpp/types/integer
就像@2501 所说的那样,您能否发布更多关于最小值的参考,因为您发布的参考并没有说明最小值。【参考方案2】:
以某种方式使用类型:
不要将signed
和unsigned
类型混合在一起,并且
不要截断较大类型的值,同时将它们存储在较小的类型中(溢出/下溢)
ssize_t
可能是 int
的别名,但它不是标准 C,可能是特定于环境的。
如果您的程序将在特定环境中运行,请检查是否sizeof(ssize_t) <= sizeof(int)
并使用int
。否则,使用其他类型T
,其中sizeof(T)
大于或等于sizeof(int)
和sizeof(ssize_t)
。
【讨论】:
ssize_t
不是 x86-64 系统上 int
的别名。
@larsmans:我已将其改写为“可能是 int
的别名”:)
我认为,出于实际原因,ssize_t
至少与指针大小相同,否则对最大写入大小会有不合理的限制。但我想不能保证指针的大小 >= int 的大小,还是有?
@hyde:通常,ssize_t
是 size_t
的签名对应物,但 POSIX 甚至不保证这一点。
@larsmans 是的,我想可以为 32 位操作系统提出一个论点,使其具有 size_t
32 位,但 ssize_t
更宽,以避免仅限于写入/读取地址的一半空间...【参考方案3】:
您可以使用 int 或 long int 数据类型,但是 ssize_t
是一种系统数据类型,应该用于跨平台可移植性。基本类型(例如'int')在不同的实现中可以是不同的大小。通常发生的是系统类型(在本例中为 ssize_t
)利用 C 的 typedef 功能,以便使用机器特定的数据类型大小,例如typedef signed ssize_t
(这是 SUSv3 标准数据类型的一部分)。在实现任何类型的系统级编程时,最好尽可能使用系统数据类型。
有关更详细的说明,请参阅 Linux 编程接口 (Michael Kerrisk)
【讨论】:
以上是关于使用 ssize_t 与 int的主要内容,如果未能解决你的问题,请参考以下文章
Web3.eth:溢出错误:Python int 太大而无法转换为 C ssize_t