重新用C presenting动态类型 [英] Representing dynamic typing in C

查看:121
本文介绍了重新用C presenting动态类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个动态类型语言。目前,我的目标是重新$ P $这样psented:

I'm writing a dynamically-typed language. Currently, my objects are represented in this way:

struct Class { struct Class* class; struct Object* (*get)(struct Object*,struct Object*); };
struct Integer { struct Class* class; int value; };
struct Object { struct Class* class; };
struct String { struct Class* class; size_t length; char* characters; };

我们的目标是,我应该能够通过周围的一切作为 Struct对象* 然后再通过比较发现对象的类型属性。例如,要投给使用我只想做以下(假设整数的类型为结构类* )

The goal is that I should be able to pass everything around as a struct Object* and then discover the type of the object by comparing the class attribute. For example, to cast an integer for use I would simply do the following (assume that integer is of type struct Class*):

struct Object* foo = bar();

// increment foo
if(foo->class == integer)
    ((struct Integer*)foo)->value++;
else
    handleTypeError();

问题是,据我所知,C标准不作任何结构如何存储的承诺。在我的平台上工作的。但在另一个平台结构字符串可以存储当我访问 foo->在我真的要访问上面的类 foo->值,其中显然是不好的。便携性是一个大目标在这里。

The problem is that, as far as I know, the C standard makes no promises about how structures are stored. On my platform this works. But on another platform struct String might store value before class and when I accessed foo->class in the above I would actually be accessing foo->value, which is obviously bad. Portability is a big goal here.

有替代这种方式:

struct Object
{
    struct Class* class;
    union Value
    {
        struct Class c;
        int i;
        struct String s;
    } value;
};

这里的问题是,工会占用尽可能多的空间,可以存储在工会最大的大小事。鉴于我的一些类型的很多倍大我的其他类型,这将意味着我的小类型( INT )将占据尽可能多的空间,我的大类型( 地图),这是不能接受的折衷。

The problem here is that the union uses up as much space as the size of the largest thing that can be stored in the union. Given that some of my types are many times as large as my other types, this would mean that my small types (int) would take up as much space as my large types (map) which is an unacceptable tradeoff.

struct Object
{
    struct Class* class;
    void* value;
};

这将创建重定向,这将放慢改革的步伐的水平。速度是一个目标在这里。

This creates a level of redirection that will slow things down. Speed is a goal here.

最后的选择是绕过无效* 和管理结构的内部自己。例如,为了实现上述类型测试:

The final alternative is to pass around void*s and manage the internals of the structure myself. For example, to implement the type test mentioned above:

void* foo = bar();

// increment foo
if(*((struct Class*) foo) == integer)
    (*((int*)(foo + sizeof(struct Class*))))++;
else
    handleTypeError();

这给我我想要的一切(便携性,不同规模不同类型的,等等),但至少有两个缺点:

This gives me everything I want (portability, different sizes for different types, etc.) but has at least two downsides:


  1. 狰狞,容易出错的C. code上面只计算一个成员偏移;它会得到与类型不是整数更复杂更糟糕。我也许可以缓解这一使用宏了一点,但是这将是痛苦的无论什么。

  2. 由于没有结构的再presents对象,我没有堆栈分配(的选择至少在没有实施对我自己的堆栈堆)。

  1. Hideous, error-prone C. The code above only calculates a single-member offset; it will get much worse with types more complex than integers. I might be able to alleviate this a bit using macros, but this will be painful no matter what.
  2. Since there is no struct that represents the object, I don't have the option of stack allocations (at least without implementing my own stack on the heap).

基本上,我的问题是,如何才能得到没有为它付出我想要什么?有没有办法可移植的,有差异的大小不同的类型,不要使用重定向,并保持我的code pretty?

Basically, my question is, how can I get what I want without paying for it? Is there a way to be portable, have variance in size for different types, not use redirection, and keep my code pretty?

编辑:这是我一生中一个SO问题收到的最好的回应。选择一个答案是很难。所以只让我选一个答案,所以我选择了带我到我的解决方案之一,但你们都收到upvotes。

This is the best response I've ever received for an SO question. Choosing an answer was hard. SO only allows me to choose one answer so I chose the one that lead me to my solution, but you all received upvotes.

推荐答案

请参阅Python的PEP 3123(的 http://www.python.org/dev/peps/pep-3123/ )为Python如何解决使用标准C. Python的解决方案,这个问题可以直接应用到您的问题。从本质上讲,你要做到这一点:

See Python PEP 3123 (http://www.python.org/dev/peps/pep-3123/) for how Python solves this problem using standard C. The Python solution can be directly applied to your problem. Essentially you want to do this:

struct Object { struct Class* class; };
struct Integer { struct Object object; int value; };
struct String { struct Object object; size_t length; char* characters; };

您可以放心地投整数* 对象* 对象* 整数* 如果你知道你的对象是一个整数。

You can safely cast Integer* to Object*, and Object* to Integer* if you know that your object is an integer.

这篇关于重新用C presenting动态类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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