Можно ли добавить вывод типа на язык Си? - PullRequest
14 голосов
/ 29 июня 2011

Допустим, мы создаем повторную реализацию C, с той лишь разницей, что эти типы выводятся. Классы хранения и модификаторы все еще должны быть данный (const, static, restrict и т. д.), и давайте ограничим наше внимание одним файл с программами на данный момент. Можно ли это сделать? Каковы основные препятствия?

Некоторые мысли о том, что может вызвать проблемы с выводом типа

  • структуры с тем же именем поля должны быть устранены неоднозначно вручную
  • то же самое для союзов с одинаковыми именами полей
  • приведению, вероятно, понадобится аннотация "from", что-то вроде

    var i = (uint32_t -> uint64_t) *some_pointer;
    

Эти проблемы потребуют небольшой аннотации пользователя, но не должны быть слишком обременительно, есть ли какая-то проблема убийства, которая выбрасывает эту идею из воды?

Редактировать: Чтобы уточнить, я не говорю о добавлении обобщения или параметрического полиморфизма, просто вывод типа для существующих типов C.

Редактировать 2014: Любой, кто интересуется этой концепцией, может захотеть изучить Rust

Ответы [ 6 ]

10 голосов

GCC 5.1 поддерживает:

6 голосов
/ 29 июня 2011

C автоматически продвигает некоторые типы, что усложняет ситуацию. Но для того, чтобы быть работоспособным, вам нужно иметь несколько дополнительных отличий от C в том виде, в котором он существует: сейчас стандарт все еще поддерживает в некоторой степени устаревшие программы K & R C, и для этого требуется, чтобы неопределенные типы обрабатывались особым образом. (См., Например, правила для параметров функций при отсутствии прототипов. Раньше также можно было указывать функции и переменные с типом no , и они будут иметь значение по умолчанию (int). (Как для переменных? Только класс хранения. static foo;)) Вся эта обработка устаревших типов должна быть удалена, прежде чем можно будет добавить новый механизм подразумеваемых типов.

4 голосов
/ 29 июня 2011

Чтобы вывести типы полиморфных функций, потребуются значительные расширения системы типов C.Пример

length(p) {
  if (p == NULL) return 0;
  else return 1 + length(p->next);
}

Этот код должен работать с любым указателем на структуру (или объединение) с полем next.Вы можете проверить полиморфизм строк, но, по крайней мере, ваша новая система типов должна быть гораздо более выразительной, чем система типов C.

Другая насущная проблема - перегруженная операция +.Какой тип по умолчанию?Вы хотите, чтобы он был перегружен любым числовым типом, например, Haskell или C ++?Если так, то более крупные расширения системы типов.

Чем больше урок , тем лучше .Преимущества C (как языка, помимо множества прекрасных API, доступных в C):

  • Вы имеете полный контроль над представлением ваших данных.
  • Любое лицо, проверяющееИсходный код может легко предсказать затраты времени и пространства.

Эта повестка дня не совсем совместима с полиморфизмом, и полиморфизм является основным преимуществом вывода типов.Если вам нужен вывод типов, выберите один из множества хороших языков (F #, Haskell, ML), которые поддерживают его изначально.

1 голос
/ 31 октября 2016

Можно сделать некоторый вывод типа в C. Посмотрите на этот инструмент: http://cuda.dcc.ufmg.br/psyche-c. Вы можете набрать часть программы там, и она восстановит отсутствующие объявления типов,Например, если мы добавим в него программу Нормана:

int length(T p) {
  if (p == NULL) return 0;
  else return 1 + length(p->next);
}

, то psyche-c найдет эти объявления:

#include <stdint.h>
#define NULL ((void*)0)
typedef int bool;
bool false = 0;
bool true = 1;
typedef  struct T {struct T* next;}* T;

Этот вид реконструкции типа полезен для завершения кодаНапример.

0 голосов
/ 29 июня 2011

В некоторых ситуациях, на мой взгляд, нельзя использовать логически выведенные типы:

  • указателям нужен определенный тип
  • массивам нужен определенный тип
  • параметры функциинужен тип

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

Даже для чего-то такого простого, как вычисление контрольной суммы, необходим определенный тип

crc8 = 0x00; /* 8 bits; cf uint8_t crc8 = 0; */
crc32 = 0x00000000; /* 32 bits; cf uint32_t crc32 = 0; */

Это может быть сделано для ограниченного использования.

0 голосов
/ 29 июня 2011

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

...