我想写一个函数,它返回一个指针指向两个特殊函数寄存器(SFR)中的一个。这些SFR有不同的类型,但它们的类型除了名字之外是相同的:
#define SFRxType SFR0Type
typedef struct SFR0Type {
union {
struct {
uint16_t var0;
uint16_t var1;
};
struct {
uint32_t var;
};
};
} SFR0Type;
extern volatile SFR0Type SFR0 __attribute__((__sfr__));
typedef struct SFR1Type {
union {
struct {
uint16_t var0;
uint16_t var1;
};
struct {
uint32_t var;
};
};
} SFR1Type;
extern volatile SFR1Type SFR1 __attribute__((__sfr__));
(The __sfr__
属性告诉编译器变量地址是由链接器脚本设置的。)
这些typedef驻留在一个我不拥有的头文件中,所以我不能更改它们。
我的函数如下所示:
static volatile SFRxType* get_sfr_ptr(uint16_t select) {
return select ? &SFR1 : &SFR0;
}
但是,这会产生编译器警告:warning: pointer type mismatch in conditional expression
.
在上述约束条件下,如何编写这样的函数而不生成警告?
2条答案
按热度按时间ecfdbz9o1#
两个选项是:
1.将
return select ? &SFR1 : &SFR0;
更改为return select ? (volatile SFRxType *) &SFR1 : &SFR0;
。调用方将负责将返回的指针强制转换为正确的类型。1.将
get_sfr_ptr
的声明更改为static void *get_sf_ptr(uint16_t select)
,并将return
语句更改为return select ? (volatile void *) &SFR1 : (volatile void *) &SFR0;
。调用方将负责将返回的指针用作其正确的类型。eeq64g8w2#
?:
并不适合,因为它要求第二个和第三个操作数的类型要么兼容,要么可以通过隐式转换使其兼容。如果使用该操作符,你必须转换类型不正确的操作数,然后从那里进入这个“语言律师”兔子洞(C17 6.5.15):此外,如果两个操作数都是指向兼容类型或兼容类型的不同限定版本的指针,则结果类型是指向复合类型的适当限定版本的指针;
不幸的是,这两个结构体 * 不 * 兼容,因为有人想出了一个坏主意,为它们使用不同的结构体标记。如果没有这些100%多余的标记,即使
typedef
名称不同,它们也会兼容。所以最好的选择可能是忘记所有隐式转换和复合类型,而是使用
if
。保持简单。无论选择哪种类型,都执行显式强制转换:但是请注意,这个返回的指针在使用之前仍然必须被强制转换为正确的类型--这也是因为结构体不兼容。