我应该如何打印类似off_t和size_t的类型?


Answers:


112

您可以将zsize_t和tptrdiff_t用于

printf("%zu %td", size, ptrdiff);

但我的联机帮助页上说,一些较早的库使用的字符不同于,z并且不鼓励使用它。但是,它是标准化的(通过C99标准)。对于那些intmax_tint8_tstdint.h等等,还有你可以使用宏,像另一个回答说:

printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);

它们列在的联机帮助页中inttypes.h

就个人而言,我只想投的价值观unsigned longlong像另一个答案建议。如果使用C99,则可以(当然应该)强制转换为unsigned long longor,long long并分别使用%lluor %lld格式。


2
off_t实际上是我系统上的长符号。
格奥尔格·

2
我认为手册页不建议使用libc5使用的Z(大写)。似乎并没有阻止z(小写)。
Draemon

12
使用%zd具有size_t不确定的行为由于符号性失配(C99 7.19.6.1#9)。一定是%zu
詹斯

7
那么,如何打印off_t呢?
JohnyTex

3
@Jens我看不出%zdsize_t来自那款或任何其他得到未定义的行为。实际上,%z#7中的定义显式允许%dwith size_t和相应的带符号类型,而§6.2.5#9显式允许在期望使用相应的带符号类型的情况下使用无符号类型的值,只要该值是有效的非负值即可。签名类型的。
Chortos-2,2013年

108

打印off_t

printf("%jd\n", (intmax_t)x);

打印size_t

printf("%zu\n", x);

打印ssize_t

printf("%zd\n", x);

请参阅C99标准中的7.19.6.1/7,或者更方便的POSIX文档格式代码:

http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html

如果您的实现不支持这些格式代码(例如,因为您使用的是C89),那么由于AFAIK的存在,C89中就不会有整数类型的格式代码,并且一定会保证它的大小。这些类型。因此,您需要做一些特定于实现的事情。

例如,如果您的编译器具有long long并且标准库支持%lld,则您可以放心地期望它将代替intmax_t。但是,如果没有,您将不得不退回到long,这在其他一些实现上会失败,因为它太小了。


3
到目前为止,这是更好的答案,我会忘记将%zu用作无符号的size_t。强制转换为intmax_t是解决任何平台上的off_t的好方法。
彼得·科德斯

2
POSIX不能保证与POSIX ssize_t具有相同的大小size_t,因此真正可移植的代码应该将其转换为intmax_t并打印,%jd就像off_t
nwellnhof

off_t的大小最长可以长,并且可以根据定义而变化... Visual Studio也会警告此警告“ C4477:'_snprintf_s':格式字符串'%jd'要求类型为'__int64'的参数,但可变参数1类型为'off_t'“ ...真正可移植的方式是printf(”%lld \ n“,(long long)x);
ericcurtin

5

对于Microsoft,答案是不同的。VS2013在很大程度上符合C99,但“不支持hh,j,z和t长度前缀。” 对于size_t“即在32位平台上为无符号__int32,在64位平台上为无符号__int64”,请使用前缀I(大写字母)以及类型说明符o,u,x或X。 请参见VS2013大小规范

至于off_t,它在VC \ include \ sys \ types.h中定义为long。


请注意,如果off_t始终long将其设置为32位(即使64位Windows也将32位用于long)。
sourcejedi 2015年

3

您正在使用哪个版本的C?

在C90中,标准做法是根据需要强制转换为有符号或无符号长,并进行相应打印。我已经看到%z的size_t,但是Harbison和Steele在printf()下没有提及它,无论如何在ptrdiff_t或其他方面都无济于事。

在C99中,各种_t类型都带有自己的printf宏,因此类似"Size is " FOO " bytes." 我不知道的细节,但这是相当大的数字格式包含文件的一部分。


3

您将要使用inttypes.h中的格式化宏。

看到以下问题: 跨平台格式的字符串是否为size_t类型的变量?


假设off_t是一个有符号的,指针大小的int(我不知道确切的定义是什么),例如ptrdiff_t,那么您将使用PRIdPTR或PRIiPTR。
Michael Burr

11
off_t类型大于在支持大文件的任何32位系统上的指针(当前是大多数32位系统)。
Dietrich Epp 2010年

1
@DietrichEpp:实际上,这比那更糟。许多32位系统同时具有off_t和off64_t,根据功能宏off_t的不同,实际上可能意味着off64_t。
SamB

1

man 3 printfLinux,OS X和OpenBSD上看,它们都显示了%zsize_t%tptrdiff_t(对于C99)的支持,但是都没有提及off_t。在野外的建议通常提供了%u转换off_t,这是“正确的足够”据我可以告诉(包括unsigned intoff_t64位和32位系统之间的变化相同)。


1
我的系统(OS X)具有32位unsigned int和64位off_t。因此,强制转换将导致数据丢失。
Dietrich Epp 2010年

-3

我至少看过两次该帖子,因为对于我而言,很难接受已接受的答案(我很少使用zj标志,它们似乎与平台无关)。

标准从未明确指出的确切数据长度size_t,因此建议您首先检查size_t平台的长度,然后选择其中一个:

if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64

而且我建议使用stdint类型而不是原始数据类型来实现一致性。


1
对于C99和C11,该标准明确规定%zu可用于打印size_t值。绝对不应该使用uint32_t/ uint64_t格式说明符来打印size_t,因为不能保证这些类型是兼容的。
自闭症患者

-4

我记得,唯一可移植的方法是将结果转换为“ unsigned long int”并使用%lu

printf("sizeof(int) = %lu", (unsigned long) sizeof(int));

1
应为“%lu”,因为长度修饰符应位于转换之前。
dwc

1
例如off_t是一个有符号的long long。
格奥尔格·

@GeorgSchölly-然后您遇到了一个难题,因为long long在C ++标准中不存在,因此本质上是不可移植的。
James Curran

-9

为off_t使用“%zo”。(八进制)或“%zu”(十进制)。


为什么要以八进制偏移文件?
poolie
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.