- UID
- 1
- 精华
- 积分
- 76365
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
size_t类型在stddef.h里面被定义,用于表示“长度”。它在32位的机器上是一个32位的无符号整数类型,而在64位的机器上则是64位的无符号整数类型,很多时候使用起来都很方便,具备跨位数兼容的可移植性,而且不用担心速度问题(在32位机器上使用64位整数比使用32位整数慢一些),十分优雅。
但由于size_t的长度是随位数变化的,如何才能优雅地使用printf来打印它呢?对于GCC编译器,使用 %zu 就可以打印size_t类型的参数,或者用scanf来获取一个size_t类型的参数的值。但对于Visual Studio 2015以前(不包括2015)带的MSVC的各种printf则不支持%zu。对于这些版本,你应该使用 %Iu 。
由于各个平台的printf对于格式字符的定义略有差异,C99推出了inttypes.h标准库头文件标准。你可以使用PRI或者SCN开头的宏来设置你想要打印的东西,而且它具有一定的规律,一般都能被猜中。它给每一个stdint.h里面定义的xintyy_t类型的整数都给出了对应的PRI或SCN版本的宏,比如PRIi64可以用于int64_t的打印,PRIu32可以用于uint32_t的打印。看下例代码:- #include<inttypes.h>
- #include<stdio.h>
- int main()
- {
- int32_t a = 1234;
- uint64_t b = 5678;
- printf("a = %"PRIi32" and b = %"PRIu64".\n", a, b);
- return 0;
- }
复制代码 会正确输出“a = 1234 and b = 5678.[换行]
”。
然而不幸的是,VS直到2012,都没有inttypes.h这个头文件,直到VS2013才加入它。而且用VS2017打开VS2012的工程也不能用,除非升级工程。此时我们可以从这个帖子里拿一份谷歌提供的针对MSVC的inttypes.h头文件。不过我觉得比起把它添加到自己的MSVC的includes里面,不如把它存为msc_inttypes.h然后放到自己的工程里面,再使用宏来判断是包含它还是包含<inttypes.h>比较好。
话说回来,inttypes.h里面并没有包含针对size_t的PRI和SCN的版本。虽说并不配套,但我还是想自己造一个“PRIsize_t”来用于打印size_t。至于为什么要这么做……我才不会告诉你我喜欢把for循环的那个i定义为size_t或者ptrdiff_t。
所以我会在我的工程的配置头文件里加上这么一堆:- #if defined(_MSC_VER)
- # include"msc_inttypes.h"
- # if _MSC_VER >= 1800
- # define PRIsize_t "zu"
- # else
- # define PRIsize_t "Iu"
- # endif
- #else
- # include<inttypes.h>
- # define PRIsize_t "zu"
- #endif
复制代码 并复制一份msc_inttypes.h进去。这份msc_inttypes.h我是不会去动它的了,所以就到处复制了。
作为对比,我的数学库mathutil则要做成一个单独的repository(注意不是resporitory),然后被别的库引用头文件和静态库。一方面我可以随时更新mathutil,只要既有接口不变动,基本上都是能兼容各种引用它的工程的,除非行为上变动很大。另一方面,静态库允许进行链接时间优化,可以避免很多优化上的问题。
参考资料:
https://en.cppreference.com/w/c/types/integer
https://devblogs.microsoft.com/c ... -in-vs2013-preview/
https://www.0xaa55.com/thread-25686-1-1.html
https://github.com/0xAA55/mathutil |
|