加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – “优雅地”解决循环依赖难题

发布时间:2020-12-16 07:06:23 所属栏目:百科 来源:网络整理
导读:所以我正在开发一种编程语言,它编译为VM执行的字节码,也编译为C作为编译为本机二进制文件的中间语言.我选择C是因为它足够低且可移植,通过重用现有的编译器而不必为每个不同的平台编写编译器以及它的怪异而节省了大量的工作. 但现有的编译器存在缺点,其中之一
所以我正在开发一种编程语言,它编译为VM执行的字节码,也编译为C作为编译为本机二进制文件的中间语言.我选择C是因为它足够低且可移植,通过重用现有的编译器而不必为每个不同的平台编写编译器以及它的怪异而节省了大量的工作.

但现有的编译器存在缺点,其中之一就是循环依赖问题.我想以一种优雅的方式解决循环依赖(不像C/C++)而不需要笨拙的前向声明,而不必使用指针和额外的间接和浪费的内存,而不必将声明与定义等分开……换句话说,像一些编程语言那样把这个问题从开发人员那里拿走.

我看待它的方式,当前的C/C++编译器的主要问题是它们不能“展望未来”,即使它不是真的未来,因为程序员的意图已经用代码表达,我的编译器没有这个问题,它不知道除了解析进度的某些特定点之外的任何事物,它知道具有循环依赖性的对象的大小并且可以计算适当的偏移等.

我已经实现了“伪造”继承,它只是继承结构成员的“内联扩展”,所以我想我也可以使用相同的方法来实际伪造聚合.在最基本和简单的例子中:

typedef struct {
    int a;
} A;

typedef struct {
    A a;
    int b;
} B;

变为:

typedef struct {
    int A_a;
    int b;
} B;

并且编译器做了一些“翻译”:

B b;
b.a.a = 7;

变为:

b.A_a = 7;

并且以相同的方式将所有结构折叠成单个根结构,其仅包含基本类型.这样,绝对没有在预先不知道尺寸的结构中使用的类型,因此定义的顺序变得无关紧要.当然,这个混乱是远离用户隐藏的,仅用于编译器的“眼睛看”,而用户端保持结构化和可读性.毫无疑问,但是为了与常规C/C++代码兼容,保留了二进制占用空间,折叠结构与使用聚合或继承的常规结构二进制相同.

所以我的问题是:这听起来像是个好主意吗?我遗失的任何可能出错的事情?

编辑:我的目的只是解决与循环依赖相关的C/C++相关困难,而不是“鸡或蛋”逻辑悖论.显而易见的是,两个对象不可能包含彼此而不会导致某种形式的无限循环.

解决方法

您无法安全地使用指向子结构的指针,因为您无法通过指向基本成员来获取指向“兼容类型”的指针.例如.后

struct Foo {
    short a;
    int b;
};

struct Bar {
    struct Foo foo;
};

struct Bar bar;

指针& bar.foo和& bar.foo.a具有不同的类型,不能互换使用.它们也不能在不违反严格别名规则的情况下强制转换为彼此的类型,从而触发未定义的行为.

每次都可以通过内联整个结构定义来避免这个问题:

struct Bar {
    struct { short a; int b; } foo;
};

现在& bar.a是指向struct {short; int;},它是struct Foo的兼容类型.

(结构类型成员和原始成员之间也可能存在填充/对齐差异,但我找不到这些的示例.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读