Почему языковые дизайнеры языка C сделали эквивалентность типов таким образом? - PullRequest
4 голосов
/ 28 апреля 2009

Я изучаю C и читаю об эквивалентности типов.

Мне любопытно, у кого-нибудь есть мнение, почему они использовали структурную эквивалентность для массивов и указателей, но они использовали декларационную эквивалентность для структур и объединений?

Почему неравенство существует? Какая польза от объявления эквивалентности со структурами / объединениями и структурной эквивалентности для всего остального?

Ответы [ 5 ]

5 голосов
/ 28 апреля 2009

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

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

4 голосов
/ 28 апреля 2009

Я уверен, что это было потому, что в то время это выглядело как хорошая идея.

Не пытайтесь переосмыслить замысел С. Кернигана и Ричи разрабатывали язык реализации системы, который мог бы быть полезен для других целей, и столкнулись с решениями, о которых они сожалели позже (приоритет работы оператора был лучше всего задокументирован). Некоторые из вопросов были рассмотрены Комитетом по стандартам, а другие слишком глубоко укоренились.

Как указывает Ури в своем ответе, эквивалентность типов - сложная проблема, и поэтому она, вероятно, будет наказана K & R в стремлении скорее получить работающий компилятор, а не проект чистого языка позже.

3 голосов
/ 28 апреля 2009

Не стоит недооценивать Денниса Ричи. Каждый статически типизированный язык должен иметь способ создания абстрактного типа , который пользователь не сможет подделать. Для этого вам понадобится конструкция типа или конструкция объявления, которая является generative , т. Е. Каждый экземпляр конструкции генерирует новый тип, отличный от любого другого. Такая конструкция жизненно необходима, если вы хотите, чтобы чужие руки не попадали в ваши данные. (Для множества примеров см. Книгу Дэйва Хэнсона C Интерфейсы и реализации .)

Так что здесь значения p1 и p2 имеют разные типы, но одно и то же представление:

struct { float x, y } p1;
struct { float x, y } p2;

Зачем выбирать struct, чтобы быть генеративным? Потому что это достаточно общее, чтобы позволить широкий спектр удобных представлений. union немного натянуто, но я подозреваю, что это «сопутствующий дизайн»; в системе типов C union ведет себя как можно большим списком struct, что упрощает компилятор.

Кстати, «эквивалентность декларации» - это термин, который я никогда не слышал раньше. 25 лет назад были популярны такие термины, как «эквивалентность имени», «структурная эквивалентность» и «эквивалентность событий». Сегодня системы типов намного более формальны, и эквивалентность обычно определяется логическими правилами, а не неформальным английским языком. Когда полезно прибегнуть к неформальному английскому языку, я обычно нахожу, что идея «генеративности» обладает большей объяснительной силой, чем придумывание нового названия для правил эквивалентности каждого нового языка.

3 голосов
/ 28 апреля 2009

Структурную эквивалентность сложно проверить. Указатели и массивы довольно просты, но структуры и типы объединений являются более сложными. Проверка на структурную эквивалентность очень сложна для этих сложных типов, но проще для указателей и массивов.

EDIT

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

Что я знаю о [эквивалентности значений], так это то, что указатели и массивы всегда имеют довольно простую компоновку в памяти. Это упрощает сравнение байтов за байтом.

Для структур и объединений эта схема памяти не обязательно настолько проста. Например, вы можете иметь структуру с целым числом (32 бита) и двойным (64 бита). Такая структура требует 128 бит памяти, 32 из которых на самом деле не актуальны для сравнения. Таким образом, сравнение между байтами и байтами исключено. Таким образом, эквивалентность декларации проще реализовать.

3 голосов
/ 28 апреля 2009

Во многих отношениях c является чистым выражением языка ассемблера 1970-х годов. Массивы на этих процессорах реализуются напрямую с помощью указателей, и они просто копируют этот факт .

...