首页 > 解决方案 > 是否有将双指针转换为单指针的编译器警告?

问题描述

考虑下面的代码,它是我做 IRL(并且已经做过几次)的简化版本,其中有一个不应该存在的“额外”地址运算符。

#define HEAD \
    int type

struct my_struct {
    HEAD;
};

struct my_struct_extended {
    HEAD;
    int a;
    int b;
};

int my_function(const struct my_struct *data) {
    return data->type;
}

struct my_struct_extended global = { 2, 3, 4 };

int main (int argc, char **argv) {
    struct my_struct_extended *local = &global;

    //        ADDRESS-OF SHOULD NOT BE HERE \/
    return my_function((struct my_struct *) &local);
}

有 to 结构,一种基本结构和一种扩展结构。扩展结构的一个实例被强制转换为要在my_function(). 然而,由于错误的地址操作符,该函数基本上开始处理垃圾数据。

当您将双指针传递给需要单指针的函数时,编译器(在我的情况下为 GCC)总是会发出警告,但是当需要强制转换结构时,会屏蔽此类错误。我猜编译器将转换解释为“是的!我真的想要这个”或其他东西。

是否有可以启用的警告来捕获此问题?

注意:真实世界的情况是涉及以下类型的演员表struct sockaddr

ret = rrr_ip_send (
    &err,
    ip_data->ip_udp.fd,
// EXTRA ADDRESS-OF    \/
    (struct sockaddr *) &addr,
    addr_len,
    (void *) send_data,
    send_size
);

标签: cgcccompiler-warnings

解决方案


这种在 C 中手工编写继承的代码并不少见,但您确实需要非常小心并定义您的函数,以根据其在层次结构中的位置严格采用继承的类型指针或基类型指针。不幸的是,您的示例中地址运算符的拼写错误只是一个错误,由于强制转换,它可以隐藏在这些设计中。减轻这种情况的一种方法是将所有转换作为单独的行表达式进行,并带有适当的注释,例如:

#define HEAD \
    int type

struct my_base_struct {
    HEAD;
};

struct my_derived_struct {
    struct my_base_struct base;
    int a;
    int b;
};

int my_base_function(const struct my_base_struct *self) {
    return self->type;
}

struct my_derived_struct global = (struct my_derived_struct){ .base.type = 2 };

int main (int argc, char **argv) {
    struct my_derived_struct *local_derived = &global;
    // get base pointer
    struct my_base_struct *base = (my_base_struct *)local_derived;

    return my_base_function(base);
}

这会提醒其他人注意正在尝试的诡计。

顺便说一句: sockaddr 结构的重载是一个臭名昭著的混乱来源。


推荐阅读