Почему в C нет объявлений переменных в логических выражениях?

Я изучаю программирование на 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. Однако, похоже, это не так. Может кто-нибудь объяснить, почему это не так?

Почему вы думаете, что int c определение можно сделать в любой точке, которую захотите? Особенно в K&R C. Ваши первоначальные ожидания верны.

i486 30.06.2024 12:45

В printf("%d", a = 5); выполняется операция a = 5, и значение «a» (то есть 5) выводится на консоль. Я подумал, что что-то вроде int c = d тоже может сработать

Abhishek01s 30.06.2024 12:58

Читая K&R, вы можете проверить приложение по синтаксису и увидеть, что выражения и объявления — это совершенно разные разделы. Вы просто не сможете их смешать.

BoP 30.06.2024 13:00
a=5 — это выражение присваивания. int c=d; — объявление с инициализатором. int c=d без завершающей запятой не является ни допустимым объявлением, ни выражением.
Weijun Zhou 30.06.2024 13:07

@BoP Спасибо за совет и разъяснения.

Abhishek01s 30.06.2024 13:23

Я считаю, что это также тот момент, где C и C++ различаются, потому что C++ допускал бы что-то вроде while(int c = getchar()), но не while((int c = getchar()) != EOF)

Lundin 01.07.2024 09:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
118
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В C объявления предназначены для информирования компилятора о том, что означает идентификатор (имя). Они указывают, что имя — это переменная определенного типа, имя типа или тег структуры и так далее.

Выражения предназначены для указания вычисления значения.

Это отдельные вещи. Объявления не являются частями выражений. Вы не можете использовать объявление в тестовом условии оператора if.

(Возможности использования «имен типов» в выражениях, например, в операнде выражения sizeof, ограничены, и эти имена типов могут объявлять структуры, объединения, перечисления и их члены. Они не являются полными объявлениями и не могут объявлять переменные. )

Правильнее было бы написать «Тем не менее, это не объявления переменных». Потому что, в частности, вы можете, например, объявить тип структуры.

Vlad from Moscow 30.06.2024 13:42

Единственное место, где вы можете использовать объявление как часть структуры управления, — это цикл 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;

C 2024 pre-publication draft

Как видите, все формы объявления должны завершаться знаком ; — практически единственное место, где это можно сделать, — это часть исходного выражения в цикле for (именно поэтому между объявлением и выражением нет ;). в грамматике выше; это предусмотрено как часть объявления). Просто нет другого места, где вы могли бы втиснуть декларацию без радикального изменения грамматики.

Другие вопросы по теме