C/C++跨平台不同数据类型打印

 欢迎大家关注我的微信公众号:Xndroid,探索Android技术,解锁移动世界。

在我们日常开发中,经常会涉及到一些Debug日志的打印,此时可能需要打印各种数据类型的变量值,从而进行诊断。

此时我们一般有两种选择,一种是使用stdout流输出的方式进行打印;另外一种则是使用printf结合占位符的形式进行打印。这里简单举例如下:

int a = 1;
int64_t b = 2;

//占位符打印
printf("%lld,%d\n", a, b);
//流输出打印
std::cout << a <<","<< b <<std::endl;

其中stdout流失输出的方式写起来不够简洁,个人不喜欢使用;相反更喜欢使用printf结合占位符的方式来进行打印。 

常规情况下,我们使用C/C++打印变量时都会使用占位符,而不同的数据类型需要搭配不同的占位符才能正常进行打印,以下是一些常用数据类型对应的占位符清单:  

数据类型占位符备注
char%c用于打印字符
char*,char[]%s用于打印以\0结尾的字符串
int%d十进制有符号整数
long%ld 十进制有符号长整型
long long%lld
unsigned int%u十进制无符号整数
unsigned int%o八进制无符号整数
unsigned int%x十六进制无符号整数,小写
unsigned int%X十六进制无符号整数,大写
unsigned long%lu 十进制无符号长整型
unsigned long long%llu
float%f浮点数
double%lf双精度浮点数
pointer%p任何指针类型

 但在某些时候,我们使用占位符打印可能会存在问题,比如此种场景:

uint64_t product_seq=45845454;
printf(“product sequence is %lu”, product_seq);

 如果我们在64位平台上进行编译运行,不会有任何问题;但如果我们在32位平台上运行,则会提示报错,报错的信息提示此处应当使用的占位符为%llu而非%lu。

这是因为uint64_t 在64位平台上对应的数据类型是unsigned long,在32位平台上则是unsigned long long,如果我们再使用%lu就会报错。

如何解决一定位长的数据在不同平台上的数据类型不一致而导致占位符打印失败呢,其实C/C++语言标准规范制定者已经考虑到了这种问题,并给出了相应的解决方案。我们在C中可以引用inttypes.h,而在C++中引用cinttypes头文件,再结合具体的宏即可实现优雅的跨平台打印。如下示例:

#C example
include <inttypes.h>
uint64_t product_seq=45845454;
printf(“product sequence is %” PRIu64, product_seq);

#C++ example
include <cinttypes>
uint64_t product_seq=45845454;
printf(“product sequence is %” PRIu64, product_seq);

 所以当我们需要跨平台打印不同位长的数据类型时,我们最好摒弃直接使用占位符进行打印的方式,转而利用官方标准定义中的宏来帮助我们进行打印,这里是一些对应表:

数据类型十进制十六进制备注
int8_tPRId8/ PRIi8
int16_tPRId16/PRIi16
int32_tPRId32/PRIi32
int64_tPRId64/PRIi64
uint8_tPRIu8PRIx8如需要大写则将x变为X
uint16_tPRIu16PRIx16如需要大写则将x变为X
uint32_tPRIu32PRIx32如需要大写则将x变为X
uint64_tPRIu64PRIx64如需要大写则将x变为X

 这里我们可以再进一步,探究其实现的原理,这里我们可以找到inttypes.h头文件,看看关于PRIu64的定义:

#define PRIu8               "u"                   /* uint8_t */
#define PRIu16              "u"                   /* uint16_t */
#define PRIu32              "u"                   /* uint32_t */
#define PRIu64              __PRI_64_prefix"u"    /* uint64_t */

这里我们可以看到PRIu64会被替换为__PRI_64_prefix"u",而__PRI_64_prefix的定义在该头文件中: 

#ifdef __LP64__
#define __PRI_64_prefix  "l"
#define __PRI_PTR_prefix "l"
#else
#define __PRI_64_prefix "ll"
#define __PRI_PTR_prefix
#endif

这段宏定义的作用其实就是根据宏__LP64__来设置__PRI_64_prefix,在不同的平台中其会被不同的值取代。由此,__PRI_64_prefix"u"在64位平台上就是lu,在32位平台上就是llu,在预处理阶段就完成了替换,从而实现了跨平台的类型适配。 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值