Можем ли мы присвоить значение внутри оператора if?

#include <stdio.h>
void main()
{
    int x = 0;
    if (x = 0)
      printf("It's zero\n");
    else
      printf("It's not zero\n");
}

Почему оператор if (x = 0) не является ошибкой? Можем ли мы присвоить такое значение в выражении if? Почему он не генерирует ошибку и почему выполняется оператор else?

Вы должны получить предупреждение от вашего компилятора, и если вы этого не сделаете, включите уровень предупреждения.

Mat 01.03.2019 16:12

Это разрешено, но следует добавить дополнительный набор скобок, чтобы указать, что вы действительно хотели проверить результат задания.

stark 01.03.2019 16:13

Да, вы можете назначать в условии, и это очень полезно, когда вам это нужно, и это вечная ловушка для новых программистов на C. Результат присваивания 0 сравнивается, чтобы убедиться, что он не равен 0; он равен 0, поэтому if ложно и else выполняется. Основная ошибка C. И утверждение эквивалентно: if ((x = 0) != 0) — лишние скобки объясняют компилятору, что вы это подразумеваете. С постоянным нулем это неразумно; с переменной, которая может быть равна нулю, это имеет смысл, и я предпочитаю явное != 0 как часть выражения. if ((x = 0)) глупо выглядит!

Jonathan Leffler 01.03.2019 16:15

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

Arif 01.03.2019 16:28
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
492
3

Ответы 3

Да, это вполне допустимый синтаксис, нет причин его запрещать.

Цитирую C11,

[...] An assignment expression has the value of the left operand after the assignment. [...]

Таким образом, значение, хранящееся в операнде LHS, будет использоваться для оценки условия оператора if.

В вашем случае переменная x содержит значение 0 после присваивания, а if (0) равно ЛОЖЬ, поэтому выполняется блок else.


Однако в большинстве случаев вместо сравнения используется синтаксис ошибочно. Вот почему большинство компиляторов выдают предупреждающее сообщение об этой конструкции.

warning: suggest parentheses around assignment used as truth value [-Wparentheses]

 if (x = 0)
 ^

Если вы уверены, что делаете, вы можете обернуть условие if выражением присваивания в дополнительную пару скобок, и все будет хорошо.

Да, разрешено присваивать значение внутри оператора if. Это очень удобно, среди прочего, когда вы хотите вызвать функцию и проверить ее возврат на наличие ошибки:

int rc;
if ((rc = check())) {
    // here rc is non-zero, often an indication of a failure
}

Обратите внимание, что я поставил дополнительную пару скобок вокруг своего присваивания — поскольку это такой вездесущий источник путаницы, компиляторы обычно предупреждают о присваивании в блоке if, предполагая, что вы могли сделать опечатку. Дополнительная пара скобок дает понять компилятору, что я именно это и имел в виду.

Кстати, здесь не создано специальное исключение, правильность этого синтаксиса проистекает из общей грамматики C - оператор присваивания оценивает присвоенное значение.

Лично мне такое заикание с двойной скобкой не нравится. Пишу if ((rc = check()) != 0). Это означает то же самое, но более явно.

Jonathan Leffler 01.03.2019 16:19

@JonathanLeffler, конечно, я считаю, что это вопрос личных предпочтений.

SergeyA 01.03.2019 16:20
int rc = check(); if ( rc != 0 )... является МНОГО менее подверженным ошибкам, а также позволяет выполнять гораздо более сложную проверку ошибок.
Andrew Henle 01.03.2019 16:24

@AndrewHenle Я не считаю эту конструкцию особенно подверженной ошибкам. Это становится еще более интересным, если вы хотите вызывать эту функцию выборочно, основываясь на результате какого-либо другого условия (используя функцию короткого замыкания). В любом случае, YMMV и никто не заставляет вас его использовать.

SergeyA 01.03.2019 16:25

@GovindParmar Я парень на С++, для меня оператор - это функция ))) Я думаю, что в C лучше оценивать.

SergeyA 01.03.2019 16:27

@SergeyA На чем ТАК ты набрал 43к+ очков репутации?!!? ;-) Вероятно, не проходит и дня без четырех или пяти вопросов о проблемах, вызванных ошибками присваивания в операторе if. Что я вижу.

Andrew Henle 01.03.2019 16:27

@AndrewHenle вряд ли аргумент. Люди также склонны возвращать указатели на локальные переменные из функций и передавать указатели по значению (и ожидать, что это изменит значение переданной переменной) - это причина для запрета локальных переменных или передачи по значению? C — сложный инструмент, и его нужно изучать. В любом случае, у вас есть свое мнение, у меня свое.

SergeyA 01.03.2019 16:29

@SergeyA едва ли аргумент Верно. Но опять же, «Посмотрите на все капли дождя» тоже не аргумент. Это будет свидетельство, поддерживающий аргумент «Идет дождь». В данном случае это присваивание в операторе if, которое приводит к ошибкам. Ссылка на другой источник ошибок не является опровержением.

Andrew Henle 01.03.2019 16:42

В C единственным требованием для оператора if является то, что он должен содержать выражение. Истинность утверждения основана на том, равно нулю ли выражение.

Оператор присваивания также оценивает присвоенное значение, поэтому if (a = 0) будет ложным, тогда как if (a = x), где x != 0 будет истинным.

Поскольку оператор присваивания является выражением, его можно поместить в оператор if, хотя частой ошибкой новичков является использование оператора присваивания там, где они намеревались использовать оператор проверки на равенство ==.

Один из способов избежать этого — ошибка: если какая-либо из сторон сравнения представляет собой r-значение, поместите его слева, так что если вы когда-нибудь случайно используете = там, где вы имели в виду ==, вы получите ошибку компиляции. Сравнивать:

if (p = NULL) // Valid syntax
    ...

if (NULL = p) // Syntax error
    ...

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