Каковы основные различия между ANSI C и K & R C? - PullRequest
42 голосов
/ 22 августа 2008

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

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

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

РЕДАКТИРОВАТЬ: Я считаю, что в книге K & R написано "ANSI C" на обложке. По крайней мере, я верю версии, которую я имею дома. Так что, может быть, больше нет разницы?

Ответы [ 11 ]

29 голосов
/ 22 августа 2008

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

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

16 голосов
/ 28 августа 2008

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

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

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

12 голосов
/ 22 августа 2008

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

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

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

6 голосов
/ 28 февраля 2011
  1. прототип функции.
  2. постоянные и изменчивые квалификаторы.
  3. поддержка широких символов и интернационализация.
  4. разрешить использование указателя функции без разыменования.
3 голосов
/ 11 сентября 2008

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

f(x)
{
    return x + 1;
}

и

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

идентичны.

2 голосов
/ 28 февраля 2013

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

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

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

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

 unsigned long foo (char* fmt, double data)
 {
      /*body of foo */
 }
2 голосов
/ 04 июня 2011
  • ПРОТОТИПИРОВАНИЕ ФУНКЦИЙ: ANSI C принимает метод прототипа функции c ++, в котором определение функции и ее объявление включают имена функций, аргументы t, типы данных и возвращаемые значения. количество типов аргументов или несовместимых аргументов. Это исправляет серьезную слабость компиляторов K & R: неправильный вызов в пользовательской программе часто проходит компиляцию, но вызывает сбой программы при их выполнении
2 голосов
/ 23 февраля 2009

Разница:

  1. Прототип
  2. поддержка широких символов и интернационализация
  3. Поддержка постоянных и изменчивых ключевых слов
  4. разрешить использование указателей на функции в качестве разыменования
1 голос
/ 06 июля 2016

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

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

  2. На платформах, где естественные средства проверки того, является ли один указатель «больше» другого, никогда не имеют побочного эффекта, кроме получения значения true или false, применение реляционных операторов к произвольным указателям также можно полагаться никогда не иметь побочных эффектов, кроме получения истинного или ложного значения.

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

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

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

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

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

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

1 голос
/ 22 августа 2008

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

...