我有一个函数,我可以用四种可能方式中的一种来编写:
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);
然后会用库函数的both方式调用:
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 的答案不同,那么我也想知道,以供将来使用。
POSIX 标准中不保证
sizeof(int) >= sizeof(ssize_t)
,反之亦然。通常 ssize_t
大于 int
,但 C99 中安全且可移植的选项是使用 intmax_t
代替参数和返回值。
您拥有的唯一保证。
int
和ssize_t
之间的关系是:
int
每个 ISO C 至少可以存储 [-2^15 ... 2^15-1] 范围内的值ssize_t
可以存储至少范围 [-1 ... 2^15-1] per POSIX 的值(另请参阅 _POSIX_SSIZE_MAX
)。(有趣的是,甚至不能保证
ssize_t
可以存储其正范围的负对应项。它不是带符号的size_t
,而是带有错误值的“大小类型”。)
以某种方式使用类型:
signed
和 unsigned
类型混合在一起并且ssize_t
可能是 int
的别名,但它不是标准 C,可能是特定于环境的。
如果您的程序将在特定环境中运行,请检查是否
sizeof(ssize_t) <= sizeof(int)
并使用int
。否则,请使用其他类型 T
,其中 sizeof(T)
大于或等于 sizeof(int)
和 sizeof(ssize_t)
。
您可以使用 int 或 long int 数据类型,但是
ssize_t
是一种系统数据类型,应该用于跨平台可移植性。基本类型(例如“int”)在不同的实现上可以有不同的大小。通常发生的情况是系统类型(在本例中为 ssize_t
)利用 C 的 typedef 功能,以便使用特定于机器的数据类型大小,例如typedef signed ssize_t
(这是 SUSv3 标准数据类型的一部分)。在实现任何类型的系统级编程时,尽可能使用系统数据类型是一种很好的做法。
有关更详细的描述,请参阅 Linux 编程接口 (Michael Kerrisk)