C також надає один з операторів, яким часто зловживають — goto, а також мітки для переходу в дане місце виконання програми. Формально, goto ніколи не потрібний і практично майже завжди можна написати код, уникаючи його. Ми не використовували goto в цій книзі.
Проте, існує декілька ситуацій, де goto може знайти собі примінення. Найпоширенішим є відмова від подальшого опрацьовування в якійсь глибоко гніздованій структурі, як наприклад вихід з двох або більше циклів одночасно. Оператора break не вистачить в таких випадках, оскільки він здійснює вихід тільки з найближчого циклу. Таким чином:
for ( ... )
for ( ... ) {
...
if (невдача)
goto error;
}
...
error:
/* очистити безлад */
Така організація зручна, коли код обробки помилки не є простим, або коли помилки можуть статися в декількох місцях.
Позначки мають ту саму форму, що й назви змінних, але закінчуються двокрапкою. Вони можуть бути приєднані до будь-якого виразу, їхня функціональність схожа до goto. Областю дії мітки є ціла функція.
Як ще один приклад, розгляньмо завдання, що полягає у виявленні, чи два масиви a і b мають якийсь спільний елемент. Одним з можливих варіантів є:
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
if (a[i] == b[j])
goto found;
/* у протилежному випадку не знайдено */
...
found:
/* знайдено: a[i] == b[j] */
...
Код з goto завжди можна написати без цього оператора, але напевне ціною додаткових тестів або додаткових змінних. Так, наприклад, пошук по масивах міг би виглядати як
found = 0;
for (i = 0; i < n && !found; i++)
for (j = 0; j < m && !found; j++)
if (a[i] == b[j])
found = 1;
if (found)
/* знайдено: a[i-1] == b[j-1] */
...
else
/* не знайдено спільних елементів */
...
За декількома винятками, як от приклади наведені тут, код, який покладається на твердженняgoto, загалом, важче зрозуміти і підтримувати у робочому стані, ніж код без goto. Хоча ми не є догматиками в цьому питанні, все ж схоже, що оператори goto слід застосовувати дуже рідко, якщо взагалі.