Типизированный против типизированного языка - PullRequest
10 голосов
/ 03 июня 2011

Я учу C и ассемблер. Я заметил, что сборка - это язык без типа по сравнению с C , который требует объявления типа данных перед обработкой данных. Но также я узнал, что даже код, написанный на C , сначала компилируется в код, написанный на ассемблере, а затем собирается в объектный код. Таким образом, это означает, что объявление типа данных, которое мы используем в C или любом другом языке высокого уровня, предназначено только для простоты компилятора C . Они не имеют никакого особого отношения к объектному коду. Это правильно?

То, что я собрал, это то, что объявление типа сообщает компилятору, что все операции могут быть выполнены с данными, размер данных (требуется для хранения данных в сегменте данных), размер максимальных и минимальных десятичных чисел, которые могут быть сохранены. Правильно ли я так сказал?

Существуют ли какие-либо другие преимущества объявления типов?

Ответы [ 4 ]

9 голосов
/ 03 июня 2011

В C у нас есть простая система типов, но она не особенно сложна, ее можно (и часто на практике) обойти с помощью полностью непроверенных приведений и т. Д. (По этим причинам C часто называют «слабо типизированным»,который плохо определен и обычно используется для разбивки языка, но, по крайней мере, говорит, что типы не , что важно.) Размер, расположение и выравнивание типов не является фиксированным, хотя обычно оно будетсоответствует одному и тому же компилятору (версии) на той же платформе.int может иметь размер 14 бит и т. Д., Это не гарантируется (за исключением того, что стандарты C требуют некоторого упорядочения между основными целочисленными типами, например, short не должно быть больше, чем int).

Программист не знает подробностей, но компилятор знает и должен знать.Например, точный код, сгенерированный для foo.y, где struct Foo { int x; short y; }; и struct Foo foo;, зависит, например, от точных размеров int и short и от дополнения struct Foo, поскольку он компилируется в «принятьадрес foo, добавить смещение y в struct Foo и использовать это ".Даже struct Foo foo; требует точного знания struct Foo (и, рекурсивно, типов, из которых он состоит) - сгенерированный код должен знать точное sizeof(struct Foo), чтобы зарезервировать нужное количество байтов в стеке?Точно так же объявления типов необходимы, чтобы знать, какие коды операций использовать для математики (iadd или fadd или сложение? Должен ли быть расширен один из операндов и до какого размера?), Сравнений, размера шага при выполнении арифметики указателя (p + n фактически добавляет n * sizeof(*p)) и т. Д. Это также предотвращает доступ к несуществующим элементам (и, как следствие, передачу значений функциям, которые затем столкнутся с этой проблемой - т.е. несоответствие типов), но это больше похоже на удобный побочный эффект- компилятор считает это ошибкой, потому что он не знает, какой код генерировать, а не потому, что он считает, что программисты похожи на детей, которых нужно наблюдать и поддерживать в порядке.

На языке ассемблера (обычно - только вчера я читало проекте в Microsoft Research, который разрабатывает типизированный, проверяемый язык ассемблера для ОС, защищенной от определенных ошибок по построению), у вас на самом деле нет типов.У вас есть байты.Вы берете N байтов из некоторого места, делаете с ними что-то и сохраняете их в каком-то месте.Да, регистры имеют фиксированный размер слова, а некоторые могут быть предназначены для специальных типов значений (например, выделенные регистры с плавающей запятой с 80 или более битами), но в основном вы можете хранить все, что угодно, где угодно.Никто не мешает вам где-то хранить 8 байтов, позже читая только последние 4 байта и добавляя их со своим счетчиком цикла, чтобы сформировать адрес для хранения возвращаемого значения в.

В других языках система типов намного сильнеепозволяя огромный диапазон расширений, которые позволяют программировать на более высоком уровне, такие как абстрагирование точных типов (и, следовательно, их расположение и типирование) и просто использование любого типа, который выполняет определенный контракт.Он допускает сигнатуры типа, такие как [a] -> a, который является функцией, принимающей список, содержащий любое значение (если оно однородно, например, список целых чисел, список строк, список списков).символов и т. д.) и возвращает один из его элементов без «стирания» (например, приведение к void *) типа.(В зависимости от реализации, он может на самом деле генерировать несколько реализаций, каждая для одного типа с известным макетом, для производительности - но это не проникает в программиста.)

3 голосов
/ 28 января 2012

Многое можно сказать о типах и их значении для программирования. И то, что вы видите в Си, даже не верхушка айсберга. Скорее, это грязный снежный ком, который кто-то выбросил на кончик айсберга. :) Первые несколько страниц следующей классической статьи объясняют некоторые основные достоинства систем типов:

http://www.lucacardelli.name/Papers/TypeSystems.pdf

Позвольте мне добавить две вещи.

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

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

Вот недавняя статья в CACM, в которой обсуждаются (среди прочего) преимущества системы типов, найденные в функциональном языке OCaml:

http://cacm.acm.org/magazines/2011/11/138203-ocaml-for-the-masses/

1 голос
/ 03 июня 2011

Да, вы в значительной степени прибили это. Печатание - просто удобная абстракция. Важно то, как вы используете сырые биты. Набор текста помогает вам использовать эти биты по назначению.

Обновление

В некотором смысле, это помогает обеспечить правильность вашей программы, устраняя некоторые распространенные ошибки.
Допустим, у вас было две переменные, char var1 = 'a' и int var2 = 10;. Если вы случайно попытались добавить var1 + var2, типизированный язык может выдать ошибку. Если он не был напечатан, он мог бы с радостью дать вам результат 107 и продолжать. Может быть трудно отследить, откуда взялся 107, пока вы не поймете, что ASCII-представление a равно 97.

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

0 голосов
/ 28 января 2012

OR ....

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

'a' + 7 

, что может вообще не быть ошибкой в ​​зависимости от определения оператора "+".

...