Я изучаю программирование на C в K&R и, экспериментируя с примерами программ, наткнулся на этот фрагмент кода:
#include <stdio.h>
int main(){
int c;
while((c = getchar()) != EOF){
putchar(c);
}
return 0;
}
и внес небольшую модификацию:
#include <stdio.h>
int main(){
while((int c = getchar()) != EOF){
putchar(c);
}
return 0;
}
Я ожидал, что сначала будет выполнена функция getchar(), возвращающая значение int, которое будет сохранено в целочисленной переменной c, а затем будет вычислено выражение c != EOF. Однако, похоже, это не так. Может кто-нибудь объяснить, почему это не так?
В printf("%d", a = 5);
выполняется операция a = 5, и значение «a» (то есть 5) выводится на консоль. Я подумал, что что-то вроде int c = d
тоже может сработать
Читая K&R, вы можете проверить приложение по синтаксису и увидеть, что выражения и объявления — это совершенно разные разделы. Вы просто не сможете их смешать.
a=5
— это выражение присваивания. int c=d;
— объявление с инициализатором. int c=d
без завершающей запятой не является ни допустимым объявлением, ни выражением.
@BoP Спасибо за совет и разъяснения.
Я считаю, что это также тот момент, где C и C++ различаются, потому что C++ допускал бы что-то вроде while(int c = getchar())
, но не while((int c = getchar()) != EOF)
В C объявления предназначены для информирования компилятора о том, что означает идентификатор (имя). Они указывают, что имя — это переменная определенного типа, имя типа или тег структуры и так далее.
Выражения предназначены для указания вычисления значения.
Это отдельные вещи. Объявления не являются частями выражений. Вы не можете использовать объявление в тестовом условии оператора if
.
(Возможности использования «имен типов» в выражениях, например, в операнде выражения sizeof
, ограничены, и эти имена типов могут объявлять структуры, объединения, перечисления и их члены. Они не являются полными объявлениями и не могут объявлять переменные. )
Правильнее было бы написать «Тем не менее, это не объявления переменных». Потому что, в частности, вы можете, например, объявить тип структуры.
Единственное место, где вы можете использовать объявление как часть структуры управления, — это цикл for
:
selection-statement:if (expression)secondary-blockif (expression)secondary-blockelsesecondary-blockswitch (expression)secondary-blockiteration-statement:while (expression)statementdostatementwhile (expression) ;for (expressionopt;expressionopt;expressionopt)statementfor (declaration expressionopt;expressionopt)statement
где декларация является одним из:
declaration:declaration-specifiers init-declarator-listopt;attribute-specifier-sequence declaration-specifiers init-declarator-list;static_assert-declarationattribute-declarationstatic_assert-declaration:static_assert (constant-expression,string-literal) ;static_assert (constant-expression) ;attribute-declaration:attribute-specifier-sequence;
Как видите, все формы объявления должны завершаться знаком ;
— практически единственное место, где это можно сделать, — это часть исходного выражения в цикле for
(именно поэтому между объявлением и выражением нет ;
). в грамматике выше; это предусмотрено как часть объявления). Просто нет другого места, где вы могли бы втиснуть декларацию без радикального изменения грамматики.
Почему вы думаете, что
int c
определение можно сделать в любой точке, которую захотите? Особенно в K&R C. Ваши первоначальные ожидания верны.