繁体   English   中英

更正 C 中自定义整数类型的格式说明符以确保可移植性

[英]Correct format specifiers for custom integer types in C to ensure portability

我想知道自定义整数类型(例如time_tsocklen_t等)的正确printf格式说明符是什么。

例如,

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main()
{
    struct addrinfo *ai;

    if (getaddrinfo("localhost", "http", NULL, &ai) != 0) {
        printf("error\n");
        return EXIT_FAILURE;
    }

    printf("%d\n", ai->ai_addrlen);
}

尽管该程序编译并运行良好,但我对使用%d打印ai_addrlenai_addrlen ,它在struct addrinfo定义为socklen_t类型,因为不能保证socklen_tint类型。

我们如何正确打印定义为socklen_ttime_t等的整数? 我担心这里的便携性。 当程序在具有不同socklen_t定义的不同实现上编译时,我不应该修改格式说明符。

使用中间转换为intmax_t%jd说明符:

printf("%jd\n", (intmax_t) ai->ai_addrlen);

强制转换将整数放大为最大可能大小的整数,该整数能够表示任何其他有符号整数类型的值。 这里有一个小小的警告:如果sizeof(intmax_t) == sizeof ai->addrlen并且ai->addrlen是无符号的,则不适合有符号整数 ( intmax_t ) 的大值将被截断。

如果您确定打印的类型是无符号的,请改用uintmax_t%ju

j字符是一个“长度子说明符”,特别适合处理intmax_t / uintmax_t的大小,它可以与di说明符字符(对于intmax_t )或uoXx字符(对于uintmax_t )。

当类型的符号已知时, @Blagovest Buyukliev答案是最好的方法。

// if some unsigned type
printf("%ju\n", (uintmax_t) ux);

// if some signed type
printf("%jd\n", (intmax_t) x);

当该符号未知时,就会出现挑战。 宏预处理不考虑类型。 以下说明了符号问题。 如果该值只能在intmax_tuintmax_t之一中表示,则这很有用。

int main(void) {
  mystery_integer_type x = rand() - RAND_MAX/2;

  // Compiler can easily optimized one of the 2 paths out
  if (x * 0 - 1 > 0) {
    printf("Unigned %ju\n", (uintmax_t) x);
  } else {
    printf("Signed %jd\n", (intmax_t) x);
  }

}

请注意,如果类型比int/unsigned窄,则所采用的路径按“...两种类型;..." C11dr §6.5.2.2 6


尝试打印time_t时会出现一个特殊问题,C 规范没有定义符号,也没有定义它是整数还是浮点数,只是它是一个实数类型

对于time_t需要便携式打印的罕见情况,一些想法,从迂腐到随意。

    // pedantic 
    printf("%La\n", (long double) time());
    printf("%.*Le\n", LDBL_DECIMAL_DIG - 1, (long double) time());
    printf("%.*e\n", DBL_DECIMAL_DIG - 1, (double) time());
    printf("%jd\n", (intmax_t) time());
    printf("%lld\n", (long long) time());
    printf("%ld\n", (long) time());
    // casual

注意: time()可能返回(time_t)(-1)

(u)intmax_t和上述其他一些依赖于 C99/C11。
对 C99 之前的可移植性增加了未讨论的其他问题,通常会导致使用(long)(double)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM