GNU C replacement/workaround for typeof/__auto_type 应用于位字段
GNU C replacement/workaround for typeof/__auto_type applied to bit fields
GNU C 有两个扩展,它建议制作安全的宏,如 MAX
和 MIN
,这些宏将只评估一次参数:typeof
和 __auto_type
。举两个 MAX
宏的例子来演示每个宏:
#define MAX(a, b) ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a > _b ? _a : _b; \
})
#define MAX(a, b) ({ \
__auto_type _a = (a); \
__auto_type _b = (b); \
_a > _b ? _a : _b; \
})
这两个的问题是 typeof
和 __auto_type
如果用在位域上会出错。此示例代码显示使用 MAX
:
的位字段的问题
#include <stdio.h>
#include <stdint.h>
// Insert one of the MAX macros here
struct bitfields {
uint8_t a: 4;
uint8_t b: 4;
};
int main(int argc, char *args[]) {
struct bitfields x = {12, 4};
printf("%d\n", MAX(x.a, x.b));
return 0;
}
GCC 分别为 typeof
和 __auto_type
给出这些错误消息:
error: 'typeof' applied to a bit-field
error: '__auto_type' used with a bit-field initializer
所以问题是:为什么 GCC 不允许将这些与位字段一起使用(我找不到任何关于它的文档),以及可以做些什么来制作一个 MAX
评估的宏对于仍可与位字段一起使用的任何类型,仅参数一次?
这个问题有一个简单的可接受的解决方案,使用一元加运算符强制整数提升:
#define MAX(a, b) ({ \
typeof(+(a)) _a = (a); \
typeof(+(b)) _b = (b); \
_a > _b ? _a : _b; \
})
然而这种方法有几个问题:
宏使用编译器特定的扩展,例如 typeof
或 __auto_type
,以及不可移植的语句表达式 ({ ... })
。
如果 a
和 b
有不同的类型,它们并不是真正的类型安全:一个简单的表达式 MAX(1L, -1U)
甚至会根据类型的大小 long
.
此外,如果作为参数传递的表达式引用名为 _a
或 _b
.
的变量,则行为将不正确
恐怕类型化内联函数似乎是一种更好的可移植性和可读性方式,但确实需要更通用的解决方案。
您使用__typeof__(+(a))
根据默认促销获取促销类型。这至少适用于 int
类型的位域。我不确定编译器如何处理更大的位域类型的类型,这些类型是实现定义的。
GNU C 有两个扩展,它建议制作安全的宏,如 MAX
和 MIN
,这些宏将只评估一次参数:typeof
和 __auto_type
。举两个 MAX
宏的例子来演示每个宏:
#define MAX(a, b) ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a > _b ? _a : _b; \
})
#define MAX(a, b) ({ \
__auto_type _a = (a); \
__auto_type _b = (b); \
_a > _b ? _a : _b; \
})
这两个的问题是 typeof
和 __auto_type
如果用在位域上会出错。此示例代码显示使用 MAX
:
#include <stdio.h>
#include <stdint.h>
// Insert one of the MAX macros here
struct bitfields {
uint8_t a: 4;
uint8_t b: 4;
};
int main(int argc, char *args[]) {
struct bitfields x = {12, 4};
printf("%d\n", MAX(x.a, x.b));
return 0;
}
GCC 分别为 typeof
和 __auto_type
给出这些错误消息:
error: 'typeof' applied to a bit-field
error: '__auto_type' used with a bit-field initializer
所以问题是:为什么 GCC 不允许将这些与位字段一起使用(我找不到任何关于它的文档),以及可以做些什么来制作一个 MAX
评估的宏对于仍可与位字段一起使用的任何类型,仅参数一次?
这个问题有一个简单的可接受的解决方案,使用一元加运算符强制整数提升:
#define MAX(a, b) ({ \
typeof(+(a)) _a = (a); \
typeof(+(b)) _b = (b); \
_a > _b ? _a : _b; \
})
然而这种方法有几个问题:
宏使用编译器特定的扩展,例如
typeof
或__auto_type
,以及不可移植的语句表达式({ ... })
。如果
a
和b
有不同的类型,它们并不是真正的类型安全:一个简单的表达式MAX(1L, -1U)
甚至会根据类型的大小long
.此外,如果作为参数传递的表达式引用名为
的变量,则行为将不正确_a
或_b
.
恐怕类型化内联函数似乎是一种更好的可移植性和可读性方式,但确实需要更通用的解决方案。
您使用__typeof__(+(a))
根据默认促销获取促销类型。这至少适用于 int
类型的位域。我不确定编译器如何处理更大的位域类型的类型,这些类型是实现定义的。