通过在作为另一个结构的一个结构而不是第一个成员的结构之间转换指针来实现C中的继承是否合法? [英] Is it legal to implement inheritance in C by casting pointers between one struct that is a subset of another rather than first member?

查看:142
本文介绍了通过在作为另一个结构的一个结构而不是第一个成员的结构之间转换指针来实现C中的继承是否合法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在我知道我可以通过将指向 struct 的指针强制转换为此 struct

Now I know I can implement inheritance by casting the pointer to a struct to the type of the first member of this struct.

然而,纯粹作为一种学习经历,我开始想知道是否有可能以稍微不同的方式实现继承。

However, purely as a learning experience, I started wondering whether it is possible to implement inheritance in a slightly different way.

此代码合法吗?

#include <stdio.h>
#include <stdlib.h>

struct base
{
    double some;
    char space_for_subclasses[];
};

struct derived
{
    double some;
    int value;
};

int main(void) {
    struct base *b = malloc(sizeof(struct derived));
    b->some = 123.456;
    struct derived *d = (struct derived*)(b);
    d->value = 4;
    struct base *bb = (struct base*)(d);
    printf("%f\t%f\t%d\n", d->some, bb->some, d->value);
    return 0;
}

此代码似乎产生了预期的结果,但正如我们所知,这远非证明它不是UB。

This code seems to produce desired results , but as we know this is far from proving it is not UB.

我之所以如此怀疑这样的代码可能是合法的,我不能看到这里可能出现的任何对齐问题。但当然,这远远不知道没有出现这样的问题,即使确实没有对齐问题,代码可能仍然是UB由于任何其他原因。

The reason I suspect that such a code might be legal is that I can not see any alignment issues that could arise here. But of course this is far from knowing no such issues arise and even if there are indeed no alignment issues the code might still be UB for any other reason.

  • Is the above code valid?
  • If it's not, is there any way to make it valid?
  • Is char space_for_subclasses[]; necessary? Having removed this line the code still seems to be behaving itself

推荐答案

这或多或少与 struct sockaddr 使用的穷人继承相同,当前一代编译器 不可靠。演示问题的最简单方法是:

This is more-or-less the same poor man's inheritance used by struct sockaddr, and it is not reliable with the current generation of compilers. The easiest way to demonstrate a problem is like this:

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

struct base
{
    double some;
    char space_for_subclasses[];
};
struct derived
{
    double some;
    int value;
};

double test(struct base *a, struct derived *b)
{
    a->some = 1.0;
    b->some = 2.0;
    return a->some;
}

int main(void)
{
    void *block = malloc(sizeof(struct derived));
    if (!block) {
        perror("malloc");
        return 1;
    }
    double x = test(block, block);
    printf("x=%g some=%g\n", x, *(double *)block);
    return 0;
}

如果 a->一些 b->某些被标准的字母允许为同一个对象,此程序将需要打印 x = 2.0 some = 2.0 ,但是对于某些编译器并且在某些条件下(它不会在所有优化级别上发生,并且您可能必须移动 test 到它自己的文件)它打印 x = 1.0 some = 2.0 而不是。

If a->some and b->some were allowed by the letter of the standard to be the same object, this program would be required to print x=2.0 some=2.0, but with some compilers and under some conditions (it won't happen at all optimization levels, and you may have to move test to its own file) it will print x=1.0 some=2.0 instead.

标准的字母是否允许 a->一些 b->一些成为同一个对象是有争议的。请参阅 http://blog.regehr.org/archives/1466 及其链接到的文章。

Whether the letter of the standard does allow a->some and b->some to be the same object is disputed. See http://blog.regehr.org/archives/1466 and the paper it links to.

这篇关于通过在作为另一个结构的一个结构而不是第一个成员的结构之间转换指针来实现C中的继承是否合法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆