-Wincompatible-pointer-types和enum

时间:2015-12-15 08:54:25

标签: c gcc enums

short*int*的隐式强制转换打印出有关不兼容指针类型的警告(我理解为什么)。

enum*int*的隐式广播会打印相同的警告。

有一个工具snacc可生成以下代码:

typedef enum
    {
        CHARGINGCALLING = 0,
        CHARGINGCALLED = 1,
        NONECHARGING = 2
    } ChargedParty; /* ENUMERATED { CHARGINGCALLING (0), CHARGINGCALLED (1), NONECHARGING (2) }  */

typedef struct MSOriginatingSMSinSMS_IWMSC /* SET */
{
    ChargedParty* chargedParty; /* [6] IMPLICIT ChargedParty OPTIONAL */
} MSOriginatingSMSinSMS_IWMSC;

#define BEncChargedPartyContent BEncAsnEnumContent

int BEncMSOriginatingSMSinSMS_IWMSCContent (BUF_TYPE b, MSOriginatingSMSinSMS_IWMSC *v) {
    BEncChargedPartyContent (b, (v->chargedParty));
    ...
}

此工具附带的标头文件:

int BEncAsnIntContent (BUF_TYPE b, int *data);
#define BEncAsnEnumContent BEncAsnIntContent

BEncChargedPartyContent的调用会打印警告。

我是否可以修改BEncAsnEnumContent的声明,使其在没有任何枚举的警告提示的情况下接受,但不是void*short*

当然使用sed我可以用静态函数替换宏BEncChargedPartyContent

static AsnLen BEncChargedPartyContent (BUF_TYPE b, ChargedParty *data)
{
    return BEncAsnEnumContent(b, (int*)data);
}

但是它们太多了。

2 个答案:

答案 0 :(得分:0)

你自己的静态功能建议听起来并不那么糟糕。

  

我可以修改BEncAsnEnumContent的声明吗?   接受没有警告指针任何枚举,但不是   void*short*

如果需要,可以使用John Zwinck暗示的静态断言。

#define BEncAsnEnumContent(b, d)        ({\
    _Static_assert(sizeof(int) == sizeof *(d), "wrong data size");\
        BEncAsnIntContent(b, (int *)d); })

您在下面的评论中所提到的是一种可行的替代方案,其优势在于它允许不同大小的枚举;这就是我理解你的意思:

#define BEncAsnEnumContent(b, d)    MyEncAsnEnumContent(b, *(d))
static int MyEncAsnEnumContent(BUF_TYPE b, int val)
{
    return BEncAsnIntContent(b, &val);
}

答案 1 :(得分:0)

枚举常量,即枚举声明中的值列表,保证为int类型。但是,这不适用于enum变量本身。 enum不需要与int兼容,也不能与另一个不同的enum类型变量兼容。大小可能因情况而异,也可能因编译器而异。

这是问题的根源。如果您将enumint或两个不同的枚举相互混合,如果它们具有相同的大小,则一切正常。然后它们是兼容的,您可以将指针从其中一种类型转换为另一种类型而不会出现问题。

但是,如果它们的大小不同,则无法执行此操作。它会提供不兼容的类型:您会违反严格的别名规则,也可能存在对齐问题。另外显而易见的是:如果你试图从只存储一小部分数据的位置读取大量数据,那么就不知道你最终会得到什么。

可靠的解决方案是将您的函数更改为仅使用整数类型而不是指针:

int BEncAsnIntContent (BUF_TYPE b, int data);

似乎并不是他们首先通过指针传递参数的原因。保持简单。