C中自定义整数类型的正确格式说明符以确保可移植性
我想知道对于自定义整数类型,如C中自定义整数类型的正确格式说明符以确保可移植性,c,cross-platform,portability,C,Cross Platform,Portability,我想知道对于自定义整数类型,如time\u t,socklen\u 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 ad
time\u t
,socklen\u 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);
}
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{
结构addrinfo*ai;
if(getaddrinfo(“localhost”、“http”、NULL和ai)!=0){
printf(“错误\n”);
返回退出失败;
}
printf(“%d\n”,ai->ai\u addrlen);
}
虽然该程序编译和运行良好,但我不喜欢使用%d
打印ai_addrlen
,它被定义为struct addrinfo
中的socklen\u t
类型,因为无法保证socklen\u t
是int
类型
如何正确打印定义为
socklen\u t
、time\u t
等的整数。?我担心这里的可移植性。当程序在具有不同定义的不同实现上编译时,我不必修改格式说明符socklen\u t
使用中间转换来intmax\u 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\u t
/uintmax\u t
的大小,它可以与d
或i
说明符(用于intmax\u
)或u
、o
、X
字符一起使用(对于uintmax\t
)。当已知类型的符号度时,答案是最佳方法
// if some unsigned type
printf("%ju\n", (uintmax_t) ux);
// if some signed type
printf("%jd\n", (intmax_t) x);
当不知道符号大小时,会发生质询。宏预处理不考虑类型。以下说明了符号大小问题。如果值仅可在intmax\u t
和uintmax\u 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
在尝试打印
时间时会出现一个特殊问题,C规范没有定义符号度,也没有定义它是整数还是浮点,只是它是实类型
对于极少数情况下需要便携式打印的time\u 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)(-1)
(u)intmax\u t
和上述其他一些函数依赖于C99/C11。
C99之前版本的可移植性增加了未讨论的其他问题,通常导致使用(长)
或(双)
除了大小
之外,任何其他标准(C、POSIX或其他)都没有特殊格式类型。您必须实际知道底层类型是什么。幸运的是,GCC和Clang非常擅长了解它,并且在使用错误的格式时会发出警告。不幸的是,如果您的代码必须在不同的平台上构建,并且具有不同大小的类型,那么这并没有真正的帮助。您没有显示结构
,但是rsize\u t
您使用的是printf(“%zu”,…)
@WeatherVane:long
不能保证是可用的最大整数,尽管在大多数当前的实现中它是.C99明确定义的intmax\u t
。@BlagovestBuyukliev我很抱歉,intmax\u t
在stdint.h
中,谢谢。@Joachim Pileborg“除了size\u t
之外,对于任何其他标准的…类型都没有特殊的格式”。对于ptrdiff\u t
宏,有t
,例如“td”
和j
对于(u)intmax\u t
。还有SCN…
和PRI…
宏,它们包含一些适用于这些类型的字符串。