如何使用printf显示off_t、nlink_t、size_t和其他特殊类型?

时间:2022-09-06 20:11:05

In my program, I stat the files they want and send the data over. The fields of a stat struct are all special types:

在我的程序中,我统计他们想要的文件,然后把数据发送过来。stat struct的字段都是特殊类型:

struct stat {
  dev_t     st_dev;     /* ID of device containing file */
  ino_t     st_ino;     /* inode number */
  mode_t    st_mode;    /* protection */
  nlink_t   st_nlink;   /* number of hard links */
  uid_t     st_uid;     /* user ID of owner */
  gid_t     st_gid;     /* group ID of owner */
  dev_t     st_rdev;    /* device ID (if special file) */
  off_t     st_size;    /* total size, in bytes */
  blksize_t st_blksize; /* blocksize for file system I/O */
  blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
  time_t    st_atime;   /* time of last access */
  time_t    st_mtime;   /* time of last modification */
  time_t    st_ctime;   /* time of last status change */
};

The relevant code for my question follows:

我的问题的有关守则如下:

len = snprintf( statbuf, STAT_BUFFER_SIZE,
  "%crwxrwxrwx %lu %u %u %lld %s %s\r\n",
  S_ISDIR( filestats.st_mode ) ? 'd' : '-',
  (unsigned long ) filestats.st_nlink,
  filestats.st_uid,
  filestats.st_gid,
  (unsigned long long ) filestats.st_size,
  date,
  filename);

How do I print these types in a portable and efficient way? At first I did it without casts by guessing the correct format specifiers. Apart from being an annoying programming habit, this also meant my code wouldn't work on a 32 bit system. Now with the casts it seems to work, but on how many platforms?

如何以可移植和有效的方式打印这些类型?一开始我没有通过猜测正确的格式说明符来进行强制转换。除了讨厌编程之外,这也意味着我的代码不能在32位系统上运行。现在有了石膏模型,它似乎可以工作了,但是在多少平台上呢?

1 个解决方案

#1


25  

There isn't a fully portable way to do it, and it is a nuisance.

没有一种完全可移植的方法来实现它,而且它是一个麻烦。

C99 provides a mechanism for built-in types like size_t with the %zu notation (and there are some extra, similar qualifiers).

C99为内置类型提供了一种机制,比如size_t,带有%zu表示法(还有一些额外的、类似的限定符)。

It also provides the <inttypes.h> header with macros such as PRIX32 to define the correct qualifier for printing a 32-bit hexadecimal constant (in this case):

它还提供 标头,使用PRIX32等宏定义用于打印32位十六进制常量的正确限定符(在本例中): 。h>

printf("32-bit integer: 0x%08" PRIX32 "\n", var_of_type_int32_t);

For the system-defined types (such as those defined by POSIX), AFAIK, there is no good way to handle them. So, what I do is take a flying guess at a 'safe' conversion and then print accordingly, including the cast, which is what you illustrate in the question. It is frustrating, but there is no better way that I know of. In case of doubt, and using C99, then conversion to 'unsigned long long' is pretty good; there could be a case for using a cast to uintmax_t and PRIXMAX or equivalent.

对于系统定义的类型(比如POSIX定义的类型)AFAIK,没有很好的方法来处理它们。所以,我所做的就是在一个“安全”的转换上做一个快速的猜测,然后相应地打印出来,包括演员阵容,这就是你在问题中所阐述的。这令人沮丧,但我知道没有更好的办法。如果有疑问,使用C99,然后转换成“无符号长”是很好的;可以使用cast到uintmax_t和PRIXMAX或等效项。

Or, as FUZxxl reminded me, you can use the modifier j to indicate a 'max' integer type. For example:

或者,正如FUZxxl提醒我的那样,您可以使用modifier j来指示一个“max”整数类型。例如:

printf("Maximal integer: 0x%08jX\n", (uintmax_t)var_of_type_without_format_letter);

#1


25  

There isn't a fully portable way to do it, and it is a nuisance.

没有一种完全可移植的方法来实现它,而且它是一个麻烦。

C99 provides a mechanism for built-in types like size_t with the %zu notation (and there are some extra, similar qualifiers).

C99为内置类型提供了一种机制,比如size_t,带有%zu表示法(还有一些额外的、类似的限定符)。

It also provides the <inttypes.h> header with macros such as PRIX32 to define the correct qualifier for printing a 32-bit hexadecimal constant (in this case):

它还提供 标头,使用PRIX32等宏定义用于打印32位十六进制常量的正确限定符(在本例中): 。h>

printf("32-bit integer: 0x%08" PRIX32 "\n", var_of_type_int32_t);

For the system-defined types (such as those defined by POSIX), AFAIK, there is no good way to handle them. So, what I do is take a flying guess at a 'safe' conversion and then print accordingly, including the cast, which is what you illustrate in the question. It is frustrating, but there is no better way that I know of. In case of doubt, and using C99, then conversion to 'unsigned long long' is pretty good; there could be a case for using a cast to uintmax_t and PRIXMAX or equivalent.

对于系统定义的类型(比如POSIX定义的类型)AFAIK,没有很好的方法来处理它们。所以,我所做的就是在一个“安全”的转换上做一个快速的猜测,然后相应地打印出来,包括演员阵容,这就是你在问题中所阐述的。这令人沮丧,但我知道没有更好的办法。如果有疑问,使用C99,然后转换成“无符号长”是很好的;可以使用cast到uintmax_t和PRIXMAX或等效项。

Or, as FUZxxl reminded me, you can use the modifier j to indicate a 'max' integer type. For example:

或者,正如FUZxxl提醒我的那样,您可以使用modifier j来指示一个“max”整数类型。例如:

printf("Maximal integer: 0x%08jX\n", (uintmax_t)var_of_type_without_format_letter);