将一个结构指针转换为另一个 - C

标签 c struct casting

请考虑以下代码。

enum type {CONS, ATOM, FUNC, LAMBDA};

typedef struct{
  enum type type;
} object;

typedef struct {
  enum type type;
  object *car;
  object *cdr;
} cons_object;

object *cons (object *first, object *second) {
  cons_object *ptr = (cons_object *) malloc (sizeof (cons_object));
  ptr->type = CONS;
  ptr->car = first;
  ptr->cdr = second;
  return (object *) ptr;
}

cons函数中,变量ptr的类型是cons_object*。但是在返回值中它被转换为object*类型。

  1. 我想知道这怎么可能,因为 cons_objectobject 是不同的结构。
  2. 这样做有什么问题吗?

任何想法!

最佳答案

这很好,并且是在 C 中实现“面向对象”的相当普遍的技术。因为 struct 的内存布局在 C 中定义明确,只要两个对象共享相同的布局,那么您可以安全地在它们之间转换指针。也就是说,type 成员的偏移量在 object 结构中与在 cons_object 结构中相同。

在这种情况下,type 成员告诉 API objectcons_object 还是 foo_object 或者一些其他类型的对象,所以你可能会看到这样的东西:

void traverse(object *obj)
{
    if (obj->type == CONS) {
        cons_object *cons = (cons_object *)obj;
        traverse(cons->car);
        traverse(cons->cdr);
    } else if (obj->type == FOO) {
        foo_object *foo = (foo_object *)obj;
        traverse_foo(foo);
    } else ... etc
}

更常见的是,我似乎将“父”类定义为“子”类的第一个成员的实现,如下所示:

typedef struct {
    enum type type;
} object;

typedef struct {
    object parent;

    object *car;
    object *cdr;
} cons_object;

这在很大程度上以相同的方式工作,除了您有一个强有力的保证,即子“类”的内存布局将与父类相同。也就是说,如果您将一个成员添加到“基础”对象,它会自动被子项拾取,您无需手动确保所有结构都同步。

关于将一个结构指针转换为另一个 - C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3766229/

相关文章:

c - 如何成对反转链表

c++ - 程序的输出是什么——异常处理?

c - 结构定义(不是实例化)应该放在头文件中吗?

c - 使用 mmap() 如何创建动态大小的结构

c# - 这会导致溢出吗?为什么,为什么不呢?

swift - 如何在 Swift 中正确支持 CGFloat 数学中的 Int 值?

c++ - 虚拟文件系统列表

c - 如果包含文件,文件中的全局变量是否可以访问?

c - 如何像nm一样打印ELF文件的符号名?

c - Visual Studio ( C ) - 打印 inf .. 我如何获得一个值?