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

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

Для начала разберемся со стадиями процесса запуска программы. Как Вы могли заметить, когда Вы запускаете программу на выполнение проходит несколько стадий:

  • Prepare for compilation. Эта стадия специфична для используемой Вами IDE, и, в общем случае, ее может не быть. Поэтому, не обращайте на нее внимания.
  • Compilation. Эта стадия, в ходе которой Ваш исходный текст обрабатывается компилятором языка C и из него получается исполняемая программа. На самом деле, это сложный, многофазный процесс. Но на данном этапе нам достаточно знать, что компилятор это такая программа, которая переводит исходный текст Вашей программы, в нашем случае записанный на языке C, в формат, понятный процессору. На данном этапе могут быть выявлены ошибки в исходном тексте Вашей программы. Это ошибки синтаксиса, то есть, не соответствие Вашей программы, правилам языка C. Но здесь не могут быть выявлены логические ошибки. Сравнивая с естественными языками, можно сказать, что здесь могут быть выявлены ошибки грамматические и пунктационные. И даже ошибки построения предложений. Но понять логику программы, то есть, насколько то, что Вы пишете является корректным, компилятор не может.
  • Running. На данной стадии програма, которая была получена на стадии компиляции выполняется процессором. То есть, все те действия, которые Вы описали в Вашей программе будут выполнены. Некоторые, самые грубые логические ошибки здесь могут проявить себя. Но не всегда.

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

Я надеюсь, что с изменением слова World на Ваше имя проблем не возникло. А вот изменения №№2-4,  должны были привести к неработоспособности Вашей программы. Давайте рассмотрим их.

Предупреждения компилятора

Когда Вы убрали строку ‘return 0;’ Вы получили предупреждение компилятора типа такого:

prog.c:7:1: warning: control reaches end of non-void function [-Wreturn-type]

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

О чем нас предупреждал компилятор? Он нас предупреждал, что наша функция non-void, то есть, она должна возвращать какое-то значение, но компилятор дошел до конца этой функции (reaches end of…) но так и не нашел возврата результата. То есть, компилятор предполагает, что Вы забыли вернуть значение из функции, которая должна это значение вернуть. И он прав!

Если Вы забыли вернуть значение из функции, то значение все таки вернется. Но случайное. И вряд-ли то, которое Вы ожидали.

Функция main обязана возвращать значение типа int. Причем общепринято, что если функция main вернула значение 0, то это означает, что программа завершила свою работу корректно. А любое другое значение – некорректно. Значение, которое возвращает функция main обрабатывается операционной системой и может быть использовано в других программах.

Несмотря на то, что компилятор выдал предупреждение, запустить такую программу все таки можно. И IdeOne делает это. Однако, при выполнении программы появляются новая ошибка.

Ошибки исполнения

Как раз при исполнении такой программы мы получаем ошибку исполнения.

Runtime error

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

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

Ошибки компиляции

После модификации №3 Вы получили другое сообщение:

prog.c:6:2: error: expected ‘;’ before ‘return’

или, если Вы не вернули строку c ‘return‘, то  такое:

prog.c:6:1: error: expected ‘;’ before ‘}’ token

Это ошибка синтаксиса. В отличие от предупреждений при наличии такой ошибки компилятор не может пустить Вас дальше. То есть, выполнить такую программу нельзя. Так как она не компилируется.

Но пока мы разберемся подробнее, что нам сообщает компилятор. В каждом сообщении компилятора сперва указывается имя файла. В данном случае это prog.c. В IdeOne Вы сами не указываете имя файла, это внутренняя кухня данной облачной IDE. Когда Вы будете пользоваться другими IDE, облачными или десктопными, или будете пользоваться компилятором без всяких IDE, имя файла будет принципиально важной информацией. Пока можете не обращать внимание на это имя файла.

После имени файла через двоточие указывается позиция в файле: строка и столбец. Это информация для Вас важна и сейчас. Однако, здесь требуется дополнительное пояснение. Обратите внимание на предупреждение (warning). В какой строке компилятор указывает наличие проблемы? Не в той строке, в которой у Вас был оператор return, а в следующей.

Аналогично и с ошибкой, котораря возникает после удаления символа точка с запятой в конце строки. Компилятор показывает, что проблема в следующей строке. Это особенность работы почти любого компилятора. Ошибка обнаруживается компилятором чаще всго  позже (по тесту программы) чем она есть на самом деле. Поэтому, получив сообщение об ошибке, Вы должны, среди прочего, посмотреть что Вы могли сделать не так ДО указанной позиции.

Еще обратите внимание, что перед ошибкой компилятор выдает строку типа такой:

prog.c: In function ‘main’:

Этим компилятор показывает в какой функции он обнаружил проблемы.

А после ошибки Вы можете увидеть строки, типа таких:

  return 0;
  ^

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

Серия предупреждений и ошибок

Все несколько сложнее, для модификации №4. Приведу здесь весь вывод компилятора.

prog.c: In function ‘main’:
prog.c:5:9: warning: missing terminating " character [enabled by default]
  printf("Hello World!);
         ^
prog.c:5:2: error: missing terminating " character
  printf("Hello World!);
  ^
prog.c:6:2: error: expected expression before ‘return’
  return 0;
  ^
prog.c:7:1: error: expected ‘;’ before ‘}’ token
 }
 ^
prog.c:7:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

Строк много: компилятор выдал три ошибки и два передупреждения. Эти сообщения могут выглядеть пугающе. Но Вы то знаете, что, на самом деле пропущен всего один символ!

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

Однако, найденное предупреждение было признано ошибкой. И компилятор выдал эквивалентную по тексту ошибку. Но, по его предположению ошибка была в другой позиции.

Все прочие ошибки и предупреждение, которые выдал компилятор это всего лишь следствие одной единственной ошибки. И на них можно не смотреть.

Итог

Итак, если Вы получили ошибку, предупреждение или пачку того и/или другого, то алгоритм Ваших действий должен быть таков:

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

Нет смысла пытаться исправить все ошибки, кроме первой. Так как, на самом деле, их скорее всего нет.

Удачи!

Следующий параграф

К оглавлению

Лицензия

Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

Programming in C for beginners by Sergey Borisov (AKA risik) is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

Программирование на языке C для начинающих автор Сергей Борисов (AKA risik) доступна на условиях лицензии Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

One thought on “Программирование на языке C для начинающих: Синтаксические ошибки, предупреждения и ошибки исполнения”

Leave a Reply