Каковы основные различия между ANSI C и K & R C?

Статья в Википедии по ANSI C гласит:

Одной из целей процесса стандартизации ANSI C было создание надмножества K & R C (первый опубликованный стандарт), включающий многие неофициальные функции, введенные впоследствии. Тем не менее, комитет по стандартам также включил несколько новых функций, таких как прототипы функций (заимствованные из языка программирования С++) и более способный препроцессор. Синтаксис объявлений параметров также был изменен, чтобы отобразить стиль С++.

Это заставляет меня думать, что есть различия. Однако я не видел сравнения между K & R C и ANSI C. Существует ли такой документ? Если нет, каковы основные отличия?

EDIT: Я считаю, что книга K & R говорит "ANSI C" на обложке. По крайней мере, я верю, что у меня есть версия. Так что, возможно, больше нет разницы?

Ответ 1

Здесь может быть некоторая путаница о том, что такое "K & R C" . Термин относится к языку, как описано в первом издании "Язык программирования C". Грубо говоря: язык ввода компилятора Bell Labs C около 1978 года.

Керниган и Ричи были вовлечены в процесс стандартизации ANSI. Диалог "ANSI C", заложенный в "K & R C" , и последующие издания "Язык программирования C" принимают соглашения ANSI. "K & R C" является "мертвым языком", за исключением того, что некоторые компиляторы по-прежнему принимают устаревший код.

Ответ 2

Прототипы функций были наиболее очевидным изменением между K & R C и C89, но было много других. Значительная часть работы пошла на стандартизацию библиотеки C. Несмотря на то, что стандартная библиотека C была кодификацией существующей практики, она кодифицировала несколько существующих практик, что затруднило ее. Книга PJ Plauger, Стандартная библиотека C, является отличной ссылкой, а также рассказывает некоторые из закулисных деталей о том, почему библиотека закончилась как это было сделано.

Стандарт ANSI/ISO C очень похож на K & R C в большинстве случаев. Предполагалось, что большинство существующих C-кода должны основываться на компиляторах ANSI без каких-либо изменений. Тем не менее, в предстандартную эпоху семантика языка была открыта для интерпретации каждым поставщиком компилятора. ANSI C привел общее описание семантики языка, которое поставило всех компиляторов на равную основу. Легко принять это как должное сейчас, спустя 20 лет, но это было значительным достижением.

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

Ответ 3

Есть некоторые незначительные отличия, но я думаю, что позже выпуски K & R предназначены для ANSI C, поэтому нет никакой реальной разницы.
"C Classic" из-за отсутствия лучших терминов имел несколько иной способ определения функций, т.е.

int f( p, q, r )  
int p, float q, double r;  
{  
    // Code goes here  
}

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

Ответ 4

  • прототип функции.
  • постоянные и неустойчивые квалификаторы.
  • широкая поддержка символов и интернационализация.
  • Позволяет использовать указатель функции без разыменования.

Ответ 5

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

f(x)
{
    return x + 1;
}

и

int f(x)
int x;
{
    return x + 1;
}

идентичны.

Ответ 6

Разница заключается в следующем:

  • Прототип
  • поддержка широких символов и интернационализация.
  • Поддержка ключевых слов const и volatile
  • разрешать указатели на функции, используемые в качестве разыменования

Ответ 7

  • FUNCTION PROTOTYPING: ANSI C использует метод прототипа функции С++, где функция definaton и декларация включает имена функций, аргументы t, типы данных и типы данных возвращаемого значения. Прототип функции разрешает ANSI ccompilers проверять вызов функции в пользовательской программе, которая пропускает недопустимый номер количество аргументов или несовместимых типов данных аргументов. Исправить основную слабость компиляторов K & RC: недействительный вызов в пользовательской программе часто передает компиляцию, но приводит к сбою программы при их выполнении.

Ответ 8

Основные отличия между ANSI C и K & R C заключаются в следующем:

  • прототипирование функций
  • поддержка спецификаторов типа const и volatile.
  • поддержка широких символов и интернационализация.
  • разрешать указатели на функции без разыменования

ANSI C использует метод прототипа функции С++, где определение функции и объявление включают имена функций, типы данных аргументов и типы данных возвращаемого значения. Прототип функции позволяет компилятору ANSI C проверять вызовы функций в пользовательских программах, которые передают недопустимые числа аргументов или несовместимые типы данных аргументов. Они фиксируют основную слабость компилятора K & R C.

Пример: для объявления функции foo и требует, чтобы foo принимал два аргумента

 unsigned long foo (char* fmt, double data)
 {
      /*body of foo */
 }

Ответ 9

Самая большая разница, я думаю, это прототипирование функций и синтаксис для описания типов аргументов функции.

Ответ 10

Основное различие, о котором еще никто не упоминал, заключается в том, что до ANSI C определялся в основном скорее прецедентом, чем спецификацией; в тех случаях, когда определенные операции будут иметь предсказуемые последствия для некоторых платформ, но не для других (например, с использованием реляционных операторов на двух несвязанных указателях), прецедент решительно выступает за предоставление гарантии платформы для программиста. Например:

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

  • На платформах, где естественным средством проверки того, является ли один указатель "больше, чем", другой никогда не имеет побочного эффекта, отличного от того, чтобы дать истинное или ложное значение, применение реляционных операторов к произвольным указателям также можно было бы полагаться никогда не иметь никаких побочных эффектов, кроме того, что дает истинное или ложное значение.

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

  • На платформах с двумя дополнениями, где целые переполнения естественным образом обматываются, операция, включающая значения без знака, меньшие, чем "int", может быть использована для того, чтобы вести себя так, как если бы значение было неподписанным в случаях, когда результат был бы между INT_MAX + 1u и UINT_MAX, и он не был увеличен до более крупного типа и не использовался как левый операнд >>, ни операнд /, %, ни любой оператор сравнения. Кстати, обоснование Стандарта дает это как одну из причин, по которой небольшие неподписанные типы способствуют подписанию.

До C89 было неясно, какие компиляторы длины для платформ, на которых вышеприведенные предположения не будут естественно выполняться, как ожидается, будут продолжать поддерживать эти допущения, но не было никаких сомнений в том, что компиляторы для платформ, которые могли бы легко и дешево следует придерживаться таких предположений. Авторы стандарта C89 не потрудились прямо сказать, что, поскольку:

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

  • Стандарт только требовал, чтобы реализации могли запускать одну возможную программу без и признавали, что, хотя тупое внедрение может рассматривать любую другую программу как вызывающую Undefined Поведение, но не думало, что это стоит беспокоиться о том, что тупые авторы компилятора пишут реализаций, которые были "соответствующими", но бесполезными.

Хотя "C89" интерпретировалось одновременно как "язык, определенный C89, плюс любые дополнительные функции и гарантии, предоставляемые платформой", авторы gcc настаивали на толковании, которое исключает любые функции и гарантии, помимо тех, которые предусмотрены C89.

Ответ 11

Несмотря на все претензии к контрагенту, K & R был и вполне способен предоставлять какие-либо вещи из нижней части рядом с оборудованием. Теперь проблема заключается в том, чтобы найти компилятор (желательно свободный), который может дать чистую компиляцию на пару миллионов строк K & R C без необходимости возиться с ним. И работает на чем-то вроде многоядерного процессора AMD.

Насколько я вижу, взглянув на источник серии GCC 4.xx, нет простого взлома, чтобы повторно активировать традиционную и -cpp-традиционную функциональность задержки до их предыдущего рабочего состояния без лишних усилий, чем я я поставил перед собой задачу. И проще построить компилятор K & R pre-ansi с нуля.