Ошибка C: в качестве левого операнда присваивания требуется lvalue - PullRequest
0 голосов
/ 06 марта 2019
#include<stdio.h>
int hailstone(int n){ 
        int length=1;
        while(1<n){(n%2)?n=3*n+1:n/=2;length++;}//error
        //while(1<n){(n%2)?n=3*n+1:(n/=2);length++;} right
        return length;
}
int main()
{
        int n;
        scanf("%d",&n);
        printf("%d\n",hailstone(n));
}

В четвертой строке есть ошибка, компилятор gcc сказал, что lvalue требуется в качестве левого операнда присваивания , но если я добавлю скобки, это будет правильно. Как и в пятой строке, и я не знаю почему.

Ответы [ 2 ]

4 голосов
/ 06 марта 2019

Несмотря на то, что вся логика сведена в одну строку, проблема на самом деле в одном выражении (простите за добавление пробелов):

(n%2) ? n=3*n+1 : n/=2

Правила приоритета для выражений C подобнытот.Назначение (и это включает составное назначение) связывает менее плотно, чем ?:.Таким образом, компилятор должен интерпретировать то, что вы написали как:

((n%2) ? n=3*n+1 : n) /=2

Поскольку ?: не выдает lvalue (что-то, что может появиться слева от назначения), вы получаете ошибку.Использование круглых скобок заставляет приоритет совпадать с тем, что вы хотели.

Но еще лучший способ написать это не быть «умным» и думать, что есть некоторая «элегантность» в использовании как можно большего количества токенов вединое выражение.Вот еще одна версия, которая гораздо удобнее для чтения и которую легче проверить как правильную:

if (n%2) {
    n = 3*n+1;
} else {
    n /= 2;
}

И это не менее эффективно, чем использование условного выражения.

0 голосов
/ 06 марта 2019

Здесь компилятор принимает значение l как

((n%2) ? n=3*n+1 : n) /

и значение r как

2

Так как ((n%2) ? n=3*n+1 : n) / = 2 является недопустимым утверждением, а значение l не являетсяпеременная, ошибка компилятора.Вы можете указать приоритет выполнения компилятору, добавив скобки.

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