Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

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

• Ссылок нет (а значит, нет и механизма передачи аргументов по ссылке).

• Нет функций-членов.

• Нет подставляемых функций (за исключением версии C99).

• Существует альтернативный синтаксис объявления функций.

Помимо этого, все остальное мало отличается от языка С++. Изучим указанные отличия по отдельности.

<p id="AutBody_Root537"><strong>27.2.1. Отсутствие перегрузки имен функций</strong></p>

Рассмотрим следующий пример:

void print(int);         /* печать целого числа */

void print(const char*); /* печать строки */ /* ошибка! */

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

void print_int(int);            /* печать целого числа int */

void print_string(const char*); /* печать строки */

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

<p id="AutBody_Root538"><strong>27.2.2. Проверка типов аргументов функций</strong></p>

Рассмотрим следующий пример:

int main

{

  f(2);

}

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

К сожалению, это определение в другом исходном файле может выглядеть следующим образом:

/* other_file.c: */

int f(char* p)

{

  int r = 0;

  while (*p++) r++;

  return r;

}

Редактор связей не сообщит об этой ошибке. Вместо этого вы получите ошибку на этапе выполнения программы или случайный результат.

  Как решить эту проблему? На практике программисты придерживаются согласованного использования заголовочных файлов. Если все функции, которые вы вызываете или определяете, объявлены в заголовке, поставленном в соответствующее место программы с помощью директивы #include, будет включен механизм проверки типов. Однако в больших программах на это трудно рассчитывать. Вследствие этого в большинстве компиляторов языка С существуют опции, предусматривающие выдачу предупреждений о вызовах необъявленных функций: воспользуйтесь ими. Кроме того, с первых дней существования языка C появились программы, с помощью которых можно выявлять все возможные проблемы, связанные непротиворечивостью типов. Обычно они называются lint. Используйте их для любой нетривиальной программы на языке С. Вы обнаружите, что программы lint подталкивают вас использовать язык С как подмножество языка С++. Одно из наблюдений, приведших к разработке языка С++, состояло в том, что компилятор мог легко проверять многое (но не все), что могли проверять программы lint.

Вы можете попросить включить проверку аргументов функций в языке С. Для этого достаточно объявить функцию с заданными типами аргументов (точно так же, как в языке С++). Такое объявление называется прототипом функции (function prototype). Тем не менее следует избегать объявлений, не задающих аргументы; они не являются прототипами функций и не включают механизм проверки типов.

int g(double); /* прототип — как в языке С ++ */

int h;       /* не прототип — типы аргументов не указаны */

void my_fct

{

  g;       /* ошибка: пропущен аргумент */

  g("asdf"); /* ошибка: неправильный тип аргумента */

  g(2);      /* OK: 2 преобразуется в 2.0 */

  g(2,3);    /* ошибка: один аргумент лишний */

  h;       /* Компилятор допускает! Результат непредсказуем */

  h("asdf"); /* Компилятор допускает! Результат непредсказуем */

  h(2);      /* Компилятор допускает! Результат непредсказуем */

  h(2,3);    /* Компилятор допускает! Результат непредсказуем */

}

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

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

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT