【问题标题】:Does dereferencing a structure pointer as a different structure's pointer alter output if I change compiler?如果我更改编译器,将结构指针取消引用为不同结构的指针会改变输出吗?
【发布时间】:2014-01-29 09:11:52
【问题描述】:

在下面的伪代码中:

#include<stdio.h>
typedef struct _apple
{
    int a;
    char b;
    float c;
} apple;

typedef struct _orange
{
    int a;
    int b;
} orange;

typedef struct _grape
{
    int a;
} grape;

void main()
{
    apple a1;
    orange o1;

    a1.a =1;
    a1.b =2;
    a1.c =3;
    o1.a =4;

    void * fruit[] = {&a1, &o1};

    grape *app = (grape*)fruit[0];

    printf ("\nRead: %d    ", app->a);
    app = (grape*)fruit[1];

    printf ("\nRead: %d    ", app->a);
}

葡萄结构是苹果和橙子的子集,因为它包含的元素顺序与苹果和橙子中的顺序相同。该程序给出的预期输出为 1 和 4。但是这种方法是否有可能因不同的编译器或任何其他特定于环境的更改而失败?

【问题讨论】:

  • 这真是一个可怕的想法 - 为您的公共结构字段使用联合。
  • 旁注:完全可以写:typedef struct something {...} something;。即,您不需要为结构指定与 typedefed 名称不同的名称(如 _orangeorange)。
  • 我不完全确定,但是如果不使用结构的成员,一些卑鄙的编译器可能会“优化”掉它们......
  • 不仅可以在全局范围内使用以下划线开头的标识符重用相同的名称(如@Shahbaz 所提到的),这是一个禁忌。这样的标识符是为编译器保留的。
  • @Shahbaz,这与头文件无关,限制适用于文件范围内的所有此类标识符,措辞对我来说一点也不含糊。这种限制的原因是允许编译器在内部使用任何此类标识符并用于链接目的。

标签: c pointers struct dereference


【解决方案1】:

您可以使用union 来处理所有类型:

typedef struct {
    /* Common elements */
    int a;
    /* Type specific */
    union {
        struct {
            char b;
            float c;
        } apple;
        struct {
            int b;
        } orange;
    } special;
} fruit;

fruit or;
or.a = 1;
or.special.orange.b = 2;
fruit * f = &or;

或者模仿对象继承:

/* Common elements (base class) */
typedef struct {
    int a;
} fruit;

/* Extended types */
typedef struct {
    fruit parent; /* Must be first */
} grape;

typedef struct {
    fruit parent; /* Must be first */
    int b;
} orange;

orange or;
or.parent.a = 1;
or.b = 2;
fruit * f1 = (fruit*)&or;
fruit * f2 = &or.parent; /* alternate type safe way */

或者使用 C++ 来获得正确的继承。

【讨论】:

  • 该项目受C语言约束。结构是标准的,模板不应该被编辑:(
  • 在那种情况下,真的别无选择。如果您想从一种类型转换为另一种类型,可移植的方法是手动一个接一个地复制结构字段。
【解决方案2】:

如果你知道你的指针指向的东西并没有真正被指针指示,你应该强制转换任何东西。但是,当您假设编译器已经以特定方式编译了某些内容时,您永远不应该进行强制转换。

当任何结构元素发生更改时,您的方法都会失败。它违反了可维护性的要求。您的方法在任何新的编译器变体上都可能失败。

【讨论】:

  • 真正的代码有大约 10-20 个结构,其中只有最后 1 或 2 个元素在变化。所以认为,取消对最后 1 或 2 个元素的所有这些结构实例的引用可以在我的特定应用程序中节省数千行代码......但是对于编译器,这可能会产生问题,然后我将被排除在没有选择之外。 ..
猜你喜欢
  • 2016-11-10
  • 2013-01-04
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多