Почему после каждого кода на C мы должны писать точку с запятой?
Почему после каждого кода на языке программирование C мы должны писать точку с запятой (;)? Я знаю, что это для того, чтобы код правильно работал, но как это работает?
Ответы (2 шт):
Одной из особенностей языка С является компактность синтаксиса, позволяющая экономить байты, используемые для хранения исходного кода. В свое время это было одним из факторов, помогавших С набирать популярность. Однако помимо ухудшения читабельности, многие синтаксические конструкции получились неоднозначными без привлечения дополнительных разделителей. Например
int x = 3;
int y = 5;
int z = x;
++y -= 2;
без разделителей выглядит как
int x = 3
int y = 5
int z = x
++y -= 2
делая невозможным отличить от
int x = 3
int y = 5
int z = x++
y -= 2
На самом деле ничего волшебного или особенного в точке с запятой нет. Она ни чем не лучше и не хуже любого другого символа в исходном коде.
Другое дело, что конкретные правила употребления того или иного символа определяются грамматикой языка. Грамматика языка C устроена так, что требует использования точки с запятой в конце объявления (англ. declaration), в конце объявления структуры (англ. struct declaration), в конце expression statement, в конце jump statement, а также в конце do while и внутри for:
(6.7) declaration: declaration-specifiers init-declarator-listopt ; (6.7.2.1) struct-declaration: specifier-qualifier-list struct-declarator-list ; (6.8.3) expression-statement: expressionopt ; (6.8.5) iteration-statement: while ( expression ) statement do statement while ( expression ) ; for ( expressionopt ; expressionopt ; expressionopt ) statement for ( declaration expressionopt ; expressionopt ) statement (6.8.6) jump-statement: goto identifier ; continue ; break ; return expressionopt ;— Отрывок из ISO/IEC 9899:1999 Appendix A.
Использование точки с запятой не является каким-то обязательным требованием. Главное, чтобы грамматика языка не была неоднозначной (англ. ambiguous).
Один из классических примеров неоднозначной конструкции в языках программирования — это «висячий else»:
/* К какому if относится этот else? */
if (a) if (b) s1; else s2;
Для решения этой неоднозначности можно ввести ключевое слово fi (так сделано в Bash); дополнительные begin и end (Pascal); или требовать, чтобы else относился к ближайшему if‡ — так сделано в C.
Точно также точка с запятой просто является инструментом для решения различных неоднозначностей в языке C, которые проявились бы, если бы этой точки с запятой не было.
† Во многих других языках программирования точка с запятой, хоть и входит в грамматику, но не является обязательной для использования и может быть опущена в некоторых контекстах. В Go, например, лексический анализатор в большинстве случаев сам вставляет точку с запятой в конце каждой строки. (Кстати, это одна из причин, почему в Go нельзя переносить фигурную скобку { на новую строку.)
‡ Этого будет достаточно в плане семантики, но чтобы избавится от неоднозначности грамматики потребуются дополнительные { и }.