C: указатели на любой тип? - PullRequest
9 голосов
/ 29 мая 2010

Я слышал, что C не настолько безопасен для типов, и думаю, что я мог бы использовать это как преимущество для моего текущего проекта.

Я разрабатываю интерпретатор с целью, чтобы виртуальная машина была чрезвычайно быстрой, намного быстрее, чем, например, Ruby и Python.

Теперь я знаю, что преждевременная оптимизация «является корнем всего зла», но это скорее концептуальная проблема.

  • Мне нужно использовать какую-то структуру для представления всех значений на моем языке (от числа к строке до списка и карты)

Возможно ли следующее?

struct Value {
 ValueType type;
 void* value;
}
  • Я бы сохранял фактические значения в другом месте, например, отдельный массив для строк и целых чисел, значение * тогда указывало бы на некоторый член в этой таблице.

  • Я бы всегда знал тип значения через переменную типа, чтобы не было проблем с ошибками типов.

Сейчас:

Возможно ли это даже с точки зрения синтаксиса и типизации?

Ответы [ 7 ]

7 голосов
/ 29 мая 2010

Если вы знаете диапазон типов, которые хотите поддерживать, это можно легко сделать с помощью union, чтобы избежать повсеместных приведений:

struct Value
{
    ValueType type;
    union
    {
        int*        iptr;
        char*       sptr;
        float*      fptr;
        struct map* mptr;

        /* ... */

        void* vptr; /* catch all, extensions */

    } ptrs;
};
7 голосов
/ 29 мая 2010

Да, вы можете использовать void*, чтобы указывать на что-либо, а затем приводить его к нужному типу при необходимости (вот как malloc и такие могут работать).

void* - это в основном «указатель на произвольный блок памяти».

2 голосов
/ 29 мая 2010

Конечно, это так. Вам понадобится только большой переключатель на type, чтобы различать тип определенного значения. Лучший тип для вашего поля type, вероятно, будет перечислением с константой для каждого типа вашего языка, например:

typedef enum type {
    Integer,
    String,
    /* and so on... */
} ValueType;

Также помните, что вы должны навести указатель void* на определенный тип перед его использованием.

0 голосов
/ 29 мая 2010

Проверьте Безопасные обратные вызовы типа CCAN для макросов, которые помогут вам избежать неудачных приведений. Я знаю, что вы не пишете обратный вызов, но многие обратные вызовы выглядят так:

void my_callback(void *context)

И несколько типов могут быть приведены к (void *) и переданы context. Приведение в этой функции становится сложным, особенно если обратный вызов запускает поток, который принимает один аргумент (void *).

В любом случае, вы можете найти несколько полезных битов, если перейдете по ссылке.

0 голосов
/ 29 мая 2010

Можно написать этот код, но, может быть, вам нужно разработать свой «язык» (хорошо, переводчик :)), прежде чем что-то другое.

Кстати, я предлагаю вам прочитать объектно-ориентированное программирование в книге c . Когда вы поняли основные понятия, вы можете посмотреть на реализацию Python Objects , чтобы вы могли подумать о том, как методы взаимодействуют с объектами и как они хранятся и т. Д.

Пока, пока!

0 голосов
/ 29 мая 2010

Хорошие новости: кто-то еще думал об этом. Смотрите вариант. (например, http://en.wikipedia.org/wiki/Variant_type и http://msdn.microsoft.com/en-us/library/x295h94e(VS.80).aspx.) Плохие новости: те из нас, кто работал с ними, обычно ненавидели их.

0 голосов
/ 29 мая 2010

Существуют различные степени безопасности типов, но поскольку язык C является строго типизированным, он фактически находится на более безопасном конце спектра. Это не помешает вам делать то, что вы предлагаете. Приведенный вами пример синтаксически допустим и может быть использован для реализации описанной вами системы. Имейте в виду, однако, что если вы пойдете дальше и попытаетесь изобрести колесо, создав собственную виртуальную машину, то вряд ли вы сравните производительность существующих языков, таких как Ruby и Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...