2012-05-09 64 views
12

typedefs的一个常见用途是使变量的“类型”能够更好地表达变量的用途,而无需重新定义其背后的存储结构。Typedefs和printf格式说明符

但是,我也看到typedefs是一种改变一类变量的存储结构的方法。

例如,如果我定义

typedef uint32_t my_offset_t 

并具有类型my_offset_t的变量,从uint32_t代码库切换到charuint64_t是改变一个线和重新编译一样简单(假设我已经使用sizeof而不是硬编码的尺寸),,除了在printf/scanf的情况下。

有没有办法根据类型以某种简单的方式交换格式说明符,而不包括围绕printf/scanf,if-elses或ifdefs的包装函数?

谢谢!

对于任何有兴趣的人,我正在修改一个LKM,它使用16位偏移量来处理32位偏移量,但希望它能够在必要时转到64位偏移量(或其他!)偏移量只需很少的更改。

回答

9

这是一个棘手的业务,但来自C99和更高版本的<inttypes.h>显示了这样做的方式。

对于您定义的每种类型,您需要为自己提供一组适当的'PRI'和'SCN'宏,小心避免标准化的名称空间。

例如,你可以使用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 

和SCN等价物。此外,你在为盐基型的等效宏来定义这些,所以:

#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 

在代码中,您使用XYZ_PRIx_my_offset_t宏建立你的格式字符串:

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

如果随后您需要将所有内容都更改为64位,相应地编辑typedef和宏定义,其余代码保持“不变”。如果你非常小心,你可以变得非常接近完全不变。

确保您在设置了很多警告的32位和64位系统上编译。海湾合作委员会不会警告你当前平台上的非问题,但他们可能会出现在另一个平台上。 (我只是修复了一些在64位上干净的代码,但是对于32位不干净的代码;它现在使用了一个像XYZ_PRId_int4而不是%d这样的宏,并且在两者上都干净地编译。)

7

如果你看一下我的earlier question on inttypes.h你可以看到系统中定义的格式说明可以在演唱会使用的类型定义(通过#define)进行自定义打印符为你的自定义类型。

+0

感谢您的回答:)我接受了另一个,虽然,因为它是一个比较完整的响应,如果任何人有兴趣在这个问题上。 – Vanwaril

0

另一种解决方案是转换和从intmax_t有符号类型和uintmax_t无符号的类型。例如:

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

如果n是任何无符号类型,将会正常工作。

对于*scanf()功能,你必须读入一个临时对象,然后分配。

(这里假设你的运行时库支持这些功能。)