简体   繁体   English

Typedef和printf格式说明符

[英]Typedefs and printf format specifiers

A common use of typedefs is to enable the 'type' of a variable to convey a better idea of a variable's purpose without redefining the storage structure behind it. typedef的一个常见用途是使变量的“类型”能够更好地了解变量的用途,而无需重新定义其后面的存储结构。

However, I'm also seeing typedefs as a way to change the storage structure for a class of variables in one go. 但是,我也看到typedef是一种改变一类变量的存储结构的方法。

For example, if I define 例如,如果我定义

typedef uint32_t my_offset_t

and have variables of the type my_offset_t , switching the code-base from uint32_t to char or uint64_t is as simple as changing one line and recompiling (assuming I've used sizeof rather than hard-coded sizes), except in the case of printf / scanf . 并且具有my_offset_t类型的my_offset_t ,将代码库从uint32_t切换到charuint64_t就像更改一行并重新编译一样简单(假设我使用的是sizeof而不是硬编码的大小), 除了printf /的情况scanf

Is there a way to swap format-specifiers according to the type in some easy way, without wrapper functions around printf / scanf , if-elses, or ifdefs? 有没有办法根据类型以一种简单的方式交换格式说明符,没有printf / scanf ,if-elses或ifdefs的包装函数?

Thanks! 谢谢!

For anyone interested, I'm modifying an LKM that used 16-bit offsets to work with 32-bit offsets, but want it to be able to go to 64-bit (or something else!) offsets if necessary with minimal changes. 对于任何感兴趣的人,我正在修改一个使用16位偏移来处理32位偏移的LKM,但是如果需要的话,希望能够以最小的变化进行64位(或其他!)偏移。

It's a tricky business, but the <inttypes.h> from C99 and later shows the way to do it. 这是一项棘手的业务,但C99及后来的<inttypes.h>显示了这样做的方法。

For each of your defined types, you need to provide yourself with an appropriate set of 'PRI' and 'SCN' macros, being careful to avoid standardized namespace. 对于每个定义的类型,您需要为自己提供一组适当的'PRI'和'SCN'宏,小心避免使用标准化的命名空间。

For example, you might use XYZ as a project-specific prefix, and produce: 例如,您可以将XYZ用作项目特定的前缀,并生成:

XYZ_PRIx_my_offset_t
XYZ_PRId_my_offset_t
XYZ_PRIX_my_offset_t
XYZ_PRIu_my_offset_t
XYZ_PRIo_my_offset_t

and the SCN equivalents. 和SCN等价物。 Further, you'd define these in terms of the the equivalent macros for the base type, so: 此外,您可以根据基类型的等效宏来定义它们,因此:

#define XYZ_PRIx_my_offset_t PRIx32
#define XYZ_PRId_my_offset_t PRId32
#define XYZ_PRIX_my_offset_t PRIX32
#define XYZ_PRIu_my_offset_t PRIu32
#define XYZ_PRIo_my_offset_t PRIo32

In your code, you build your format strings using the XYZ_PRIx_my_offset_t macros: 在您的代码中,使用XYZ_PRIx_my_offset_t宏构建格式字符串:

printf("Offset: 0x%.8" XYZ_PRIX_my_offset_t "\n", my_offset_value);

If you subsequently need to change everything to 64-bit, you edit the typedef and the macro definitions appropriately, and the rest of the code remains 'unchanged'. 如果您随后需要将所有内容更改为64位,则可以适当地编辑typedef和宏定义,其余代码保持“不变”。 If you're really careful, you can get pretty close to completely unchanged. 如果你真的很小心,你可以非常接近完全不变。

Make sure you compile on both 32-bit and 64-bit systems with lots of warnings set. 确保在设置了大量警告的32位和64位系统上进行编译。 GCC will not warn about non-problems on your current platform, but they may show up on the other. GCC不会对您当前平台上的非问题发出警告,但它们可能会出现在另一个平台上。 (I just fixed some code that was clean on 64-bit but unclean for 32-bit; it now uses a macro like XYZ_PRId_int4 instead of %d and compiles cleanly on both.) (我刚刚修复了一些在64位上干净但在32位上不干净的代码;它现在使用像XYZ_PRId_int4这样的宏而不是%d并在两者上干净地编译。)

如果您查看我之前关于inttypes.h的问题,您可以看到系统定义的格式说明符如何与typedef(通过#define )一起使用,以便为您的自定义类型创建自定义打印说明符。

Another solution is to convert to and from intmax_t for signed types and uintmax_t for unsigned types. 另一种解决方案是转换和从intmax_t有符号类型和uintmax_t的无符号类型。 For example: 例如:

printf("%ju\n", (uintmax_t)n);

will work correctly if n is of any unsigned type. 如果n是任何无符号类型,则将正常工作。

For the *scanf() functions, you'd have to read into a temporary object and then assign. 对于*scanf()函数,您必须读入临时对象然后分配。

(This assumes your runtime library supports these features.) (这假设您的运行时库支持这些功能。)

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

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