这个技巧会在C中发挥作用吗?

时间:2012-06-03 16:46:34

标签: c

我想在C中的结构中添加一个字段。例如,我有以下结构。

struct A
{
 some_type x;
 some_type y;
}

我声明了一个新的结构,就像这样。

struct B
{
 A a;
 some_type z;
}

现在说我有这样的功能。

int some_function( A * a )

是否可以在程序中将类型B的变量传递给它。

B * b;
......
A * a = (A*)b;
some_function( a );

还可以使用some_function来使用a->x中的字段吗?

5 个答案:

答案 0 :(得分:9)

是的,它是有效的。标准的话,C99 6.7.2.1/13:

  

...指向a的指针   结构对象,适当转换,指向其初始成员(或者如果该成员是a   位字段,然后到它所在的单元,反之亦然。可能有未命名的   在结构对象中填充,但不在其开头。

答案 1 :(得分:1)

是的,它会起作用。 a将是struct

中的第一个成员

这是一些人在C

中模拟OO继承的方式

您可以使用

  &b->a

而不是演员。 并且可能做一个像

这样的ASSERT
 ASSERT (&b->a == b)

当你意外地破坏了这个语义时会被警告

答案 2 :(得分:1)

为什么不在成员上调用方法?

some_function( &b->a );

您的代码现在可以使用了,但是如果有人决定更改B的成员呢?或者在a之前添加新成员?

答案 3 :(得分:0)

不,它不会起作用。如果你稍微改变它工作:

struct A
{
 some_type x;
 some_type y;
}; /* <- note semicolon here */


struct B
{
 struct A a;
 some_type z;
}; /* ... and here */


int some_function(struct A *a ); /* ... and here ... */


struct B *b;
......
struct A *a = (struct A*)b;
some_function( a );

答案 4 :(得分:0)

是的,这可行,但只是偶然。

如果我正确地回忆起C99标准,那么这个特殊情况需要按预期工作。但很明显,这只是因为在此之前有足够多的人依赖它工作,并且它在很多实施中偶然发挥作用,C99标准委员会认为有必要立法在法律上和事实上进行立法。 / p>

不要让那诱惑你认为这是个好主意。

任何依赖于标准边缘情况的东西都会在破碎的边缘永久地摇摇欲坠,因为它看起来很丑陋(因此使你的代码的未来读者感到不舒服)并且看起来很聪明(这使得他们对改变/修复任何东西感到紧张)。此外,它引导民众做出假设,因为你已经处于合法的边缘,可以诱使跨越国界的民众成为破碎的代码。例如,结构中第一个子结构中的第一个元素按预期对齐,这并不意味着任何其他子元素都排成一行。它适用于你的编译器这一事实并不意味着它对任何其他人都有效,导致令人费解的混乱错误。

写:

A *a = &(b->a);

(如上面的评论所示),你的意思很清楚。

如果由于某些不明原因你必须将B*强制转换为A*,那么请写一个非常明确的评论,解释为什么你别无选择,只能做你必须做的事情做,向读者保证它是合法的,并指向授权它的C99标准的子部分。

如果你真的找不到那个小节(并且发现它是你的作业/忏悔),那么就这样评论,我会把它挖出来。