Выражения в C. Являются ли выражения присваивания несмотря на точки с запятой?

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

Смотрите здесь: интервал а, б, с; а = б = с = 10;

int a,b,c;
b = 2; 
c = 3;
a = b + c;

Можно ли считать это всеми выражениями? или заявления

Пробовал просматривать ресурсы и получил противоречивые ответы.

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

Ответы 3

То, что сказал ваш учитель, верно, но только если вы прочитаете это особым образом.

Присваивание в C — это выражение, потому что вы можете сказать f( x = 5 ), и в этом случае 5 присваивается x, но тогда вся x = 5 — это выражение, которое оценивается как 5, а затем значение этого выражения передается в качестве параметра в функцию функция y().

Имейте в виду, что большинство программистов сочтут эту конструкцию запутанной, и в большинстве случаев она не пройдет проверку кода.

Точно так же люди часто используют if ( booleanVariable = booleanFunction() ) { ... }, который вызывает функцию, присваивает результат переменной, а затем вычисляет то же значение, которое затем проверяется оператором if. Это также считается запутанным, хотя и немного меньшим, поскольку используется очень часто.

Это также будет выражение на C: a.

(Где a ранее было объявлено как переменная некоторого типа.)

А поставив после него точку с запятой, вы можете использовать его как выражение следующим образом:

int a = 5;
a;
printf( "Hello" );

Это допустимый C. Он должен выдать предупреждение («оператор не имеет никакого эффекта»), а если это не так, то это означает, что вы пытаетесь написать код, не выяснив предварительно, как включить все предупреждения в вашем компиляторе, что крайне нежелательно, но это другая история. Дело в том, что если вы игнорируете предупреждения, это действительный C, который компилируется и запускается.

Причина этой странности в C заключается в том, что синтаксис языка был разработан таким образом, чтобы обеспечить очень простой компилятор.

Язык хотел разрешить вызов функции и игнорирование ее возвращаемого значения (например, doSomething();), а это означает, что язык должен разрешать автономные вызовы функций.

Однако вызов функции также должен быть выражением, чтобы вы могли сделать f( doSomething() );, а это означает, что компилятор должен иметь возможность разрешать автономные выражения.

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

Некоторые предложили бы if (function_call() == var) { ... } именно потому, что if (function_call() = vr) { ... } выдаст ошибку во время компиляции if (var = function_call()) { ... }.

Chris 28.08.2024 19:52
Ответ принят как подходящий

Стандарт C11 6.5.1 Выражение — это последовательность операторов и операндов, которая определяет вычисление значения, или обозначает объект или функцию, или генерирует побочные эффекты, или выполняет их комбинацию. Вычисления значений операндов оператора выполняются перед вычислением значения результата оператора.

C11 Standard 6.8.2 Оператор определяет действие, которое необходимо выполнить. Если не указано иное, операторы выполняются последовательно.

Итак, в a = b = c = 42; у нас есть 3 выражения присваивания и 1 оператор.
Выражения: a = <something>, b = <something> и c = 42. (см. C11 6.5.16)
Это утверждение эквивалентно английскому предложению «Присвойте a, b и c значения 42».

В настоящее время я изучаю C, и на одном из слайдов профессор утверждает, что добавление точки с запятой к выражению делает его утверждением.

Да, полное выражение, за которым следует точка с запятой, является «оператором выражения», который является одной из нескольких категорий операторов, распознаваемых C.

С другой стороны, упоминалось, что все присваивания являются выражениями.

Это можно интерпретировать так, как будто это правда, но это потенциально может сбить с толку. В C = — это инфиксный оператор, как и + и /. Объединение его с допустимыми левым и правым операндами, например, в x = 1, образует выражение, как и в x + 1. В этом смысле да, каждое задание является выражением.

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

Даже если эти назначения занимают дополнительные строки и должны быть разделены точкой с запятой.

Это не имеет смысла. Выражение присваивания может быть распределено по нескольким строкам:

y
   =
      42

Но если вы добавите точку с запятой, то она не будет частью выражения, и выражение не продолжится после нее. Таким образом, вы сформировали выражение-выражение.

Но можно ставить утверждения одно за другим, так что это...

b = 2; 
c = 3;
a = b + c;

... представляет собой три оператора выражения, каждый из которых содержит отдельное (полное) выражение присваивания.

С другой стороны, это...

а = б = с = 10;

... это один оператор выражения, содержащий одно, более сложное полное выражение, включающее некоторые подвыражения. Поскольку оператор = выполняет ассоциации справа налево, это эквивалентно...

a = (b = (c = 10));

Кроме того, хотя это верно и четко определено, я вхожу в число многих программистов, которые посоветовали бы вам, что подобные объединенные присваивания (в любой форме) являются плохим стилем.

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