是否可以将指针从结构类型强制转换为在C中扩展第一个结构类型的指针? [英] Is it possible to cast pointers from a structure type to another structure type extending the first in C?

查看:48
本文介绍了是否可以将指针从结构类型强制转换为在C中扩展第一个结构类型的指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,如果我有结构定义,如下所示:

If I have structure definitions, for example, like these:

struct Base {
  int foo;
};

struct Derived {
  int foo; // int foo is common for both definitions
  char *bar;
};

我可以做这样的事情吗?

Can I do something like this?

void foobar(void *ptr) {
  ((struct Base *)ptr)->foo = 1;
}

struct Derived s;

foobar(&s);

换句话说,我可以将void指针强制转换为 Base * 的类型,以在其类型实际上是 Derived * 时访问其 foo 成员吗?

In other words, can I cast the void pointer to Base * to access its foo member when its type is actually Derived *?

推荐答案

许多现实世界中的C程序都假定您显示的构造是安全的,并且对C标准(特别是通用初始序列")进行了解释.规则,即C99§6.5.2.3p5).不幸的是,自从我最初回答这个问题以来的五年中,我很容易就可以接触到的所有编译器(即GCC和Clang)都集中在对通用初始序列规则的不同,更狭义的解释上,在这种解释下,您所展示的构造会引起争议.未定义的行为.具体来说,请尝试以下程序:

Many real-world C programs assume the construct you show is safe, and there is an interpretation of the C standard (specifically, of the "common initial sequence" rule, C99 §6.5.2.3 p5) under which it is conforming. Unfortunately, in the five years since I originally answered this question, all the compilers I can easily get at (viz. GCC and Clang) have converged on a different, narrower interpretation of the common initial sequence rule, under which the construct you show provokes undefined behavior. Concretely, experiment with this program:

#include <stdio.h>
#include <string.h>

typedef struct A { int x; int y; }          A;
typedef struct B { int x; int y; float z; } B;
typedef struct C { A a;          float z; } C;

int testAB(A *a, B *b)
{
  b->x = 1;
  a->x = 2;
  return b->x;
}

int testAC(A *a, C *c)
{
  c->a.x = 1;
  a->x = 2;
  return c->a.x;
}

int main(void)
{
  B bee;
  C cee;
  int r;

  memset(&bee, 0, sizeof bee);
  memset(&cee, 0, sizeof cee);

  r = testAB((A *)&bee, &bee);
  printf("testAB: r=%d bee.x=%d\n", r, bee.x);

  r = testAC(&cee.a, &cee);
  printf("testAC: r=%d cee.x=%d\n", r, cee.a.x);

  return 0;
}

在启用优化的情况下进行编译(并且没有 -fno-strict-aliasing )时,GCC和Clang都将假定 testAB 的两个指针参数不能指向同一对象,所以我得到的输出是

When compiling with optimization enabled (and without -fno-strict-aliasing), both GCC and Clang will assume that the two pointer arguments to testAB cannot point to the same object, so I get output like

testAB: r=1 bee.x=2
testAC: r=2 cee.x=2

他们没有对 testAC 做出这样的假设,但是-以前的印象是,必须编译 testAB ,就像它的两个参数指向同一对象-我对标准的理解不再足够自信,无法确定 是否可以继续工作.

They do not make that assumption for testAC, but — having previously been under the impression that testAB was required to be compiled as if its two arguments could point to the same object — I am no longer confident enough in my own understanding of the standard to say whether or not that is guaranteed to keep working.

这篇关于是否可以将指针从结构类型强制转换为在C中扩展第一个结构类型的指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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