linux 中typeof的一些记录
问题的由来
在代码的编写过程中经常会写
if (a > b)
z = a;
else
z = b
这样逻辑简单的判断,这时我们会很自然的想到用 三目运算符( ?: ),再结合宏定义。
#define max(a,b) ((a) > (b) ? (a) : (b))
这里对于一些简单的判断代码能保证正常运行,但对于类似这样的判断,则会出错
max(a++,--b);
等多次调用会改变结果的,则会出错。
这里我们对max进行改进
#define maxint(a,b) \
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
但是并不是所有的a,b 都是int类型,如果想找一种通用的方法该如何处理。
GNU c 中的typeof
c++ 中可以使用模板
template <typename T>
const T &max(const T &a, const T &b)
{
....
}
GNU c 中 使用typeof 重新定义类型
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
所以我们在读linux 内核代码时会发现很多的地方使用了typeof
例如
#define __put_unaligned_t(type, val, ptr) do { \
struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \
__pptr->x = (val); \
} while (0)
#define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr))
static inline void put_unaligned_le16(u16 val, void *p)
{
__put_unaligned_t(__le16, cpu_to_le16(val), p);
}
static inline void put_unaligned_le32(u32 val, void *p)
{
__put_unaligned_t(__le32, cpu_to_le32(val), p);
}
上述代码宏替换后如下
put_unaligned_be16((u16)val, &buf[offset]); ->
__put_unaligned_t(__le16, cpu_to_le16(val), &buf[offset]);
#define __put_unaligned_t(type, val, ptr) do { \
struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \
__pptr->x = (val); \
} while (0)
这里常见的处理方法是定义 一个struct { type x; } 然后通过赋值的方式把val 值放到对应的8字节数组中。