簡體   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