Jump to content

    

Косяк у Кейла

Это абсолютно чистый, как слеза, Си обязательный к однозначному толкованию любым компилятором. Использовано правило по которому выражение с оператором присваивания заключенное в круглые скобки равно присваемому.
В чистом, как слеза, Си, результатом оператора '=' является левый операнд, т.е. присваиваемое, вне зависимости от наличия скобок. А вот сама запись содержимого правого операнда в левый является побочным эффектом этого оператора. Это свойство позволяет писать a= b = c; И результат этого выражения будет идентичен выражению a = (b = c);, т.е. скобки здесь никакой синтаксической роли не играют.

 

 

Проверил - Кейл выдает и там и там, что, наверное, я хотел поставить ==.
Сочувствую... gcc пишет так:

./xxxx.cpp:125:16: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
     while( c = 3 )
                ^

Со скобками, соответственно, молчит. Ждите новую версию кейла.

Share this post


Link to post
Share on other sites
Не понял столь лаконично заданного "вопроса". Насколько я мог догадаться, то да, присваивание вырабатывает значение (таков СТАНДАРТ) и по этой причне может применяться указанным образом.

rvalue это результат [выражения]. lvalue это объект имеющий тип и адрес. Почему-то считается, что у него обязано быть имя. Но мне кажется безымянный lvalue легко создаётся в выражении: *(int *)Addr, где адрес - любое число, и тип тоже любой.

 

Если бы скобки приводили любое выражение к rvalue, то нельзя было бы брать адрес lvalue через скобки и на такое выражение (var) = value выдавалась бы ошибка. Значит скобки в выражении управляют только приоритетом вычисления операторов, при этом никакую информацию выражения не обрезают. Операция присваивания без помощи дополнительных скобок приводит выражение к типу rvalue. Причём к обрезанному или расширенному до ширины типа lvalue, в котором оно сохраняется. Приведите выдержки из стандарта, опровергающие такую логику работы скобок.

 

Если какой-то компилятор при этом перестаёт ругаться, то это его фича. В тексте ошибки компиляторов не содержится указание, что ошибка находится вне области скобок выражения, подразумевается вся область выражения.

Edited by GetSmart

Share this post


Link to post
Share on other sites

Вирта на вас нет :) "В чистом, как слеза, Си" :) "Сколько чертей поместится на острие иглы" :)

Share this post


Link to post
Share on other sites
В чистом, как слеза, Си, результатом оператора '=' является левый операнд, т.е. присваиваемое, вне зависимости от наличия скобок. А вот сама запись содержимого правого операнда в левый является побочным эффектом этого оператора. Это свойство позволяет писать a= b = c; И результат этого выражения будет идентичен выражению a = (b = c);, т.е. скобки здесь никакой синтаксической роли не играют.

писать "a = b = c" БЕЗ скобок вообще-то позволяет ПРАВИЛО ассоциативности, которое для '=' справа-налево, а не слева-направо, как для, например '=='.

Так-что о к чему все это было написано не пойму :(.

Ну и кроме всего этого - а зачем ты пытаешься подменить этим a = b = c, выраженние, которое вообще-то a == b = c ?

 

Давай ты на пару с GetSmart , заглянешь хотя-бы в букварь K&R там прямо вариант while ((c = *ptr++)) рассматривается.

 

Сочувствую... gcc пишет так:

./xxxx.cpp:125:16: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
     while( c = 3 )
                ^

Со скобками, соответственно, молчит. Ждите новую версию кейла.

То есть все правильно - скобки отработали. Ну а на константное GCC традиционно не выдает предупреждений :(. Можно смело писать багрепорт на Кейл :) - называние темы таки ПРАВИЛЬНОЕ! :)

 

 

 

 

Если бы скобки приводили любое выражение

О любом речь не шла. Только в выражении содержащем оператор присваивания.

Если какой-то компилятор при этом перестаёт ругаться, то это его фича.

Вместо рассуждений, ну ознакомьтесь хоть с букварем от K&R такм Вам Автор языка покажет while ((c = *ptr++)) с "лишними" скобками.

Share this post


Link to post
Share on other sites
В чистом, как слеза, Си, результатом оператора '=' является левый операнд, т.е. присваиваемое, вне зависимости от наличия скобок. А вот сама запись содержимого правого операнда в левый является побочным эффектом этого оператора.

Не понял. Прямое действие оператора "=" в чём? Действие, не результат. Все операторы должны выполнять какое-то действие над операндами.

 

О любом речь не шла. Только в выражении содержащем оператор присваивания.

...

Вместо рассуждений, ну ознакомьтесь хоть с букварем от K&R такм Вам Автор языка покажет while ((c = *ptr++)) с "лишними" скобками.

Логику озвучьте. Или выдержку из стандарта. Потому как нелогичен такой хак компиляторов. Что дают скобки выражению с оператором присваивания до сих пор не ясно. Сам оператор приводит всё выражение из левого и правого операндов присваивания к единому целому rvalue. Скобки тут ни причём.

 

Кстати, Кейл вполне умеет определять было ли присваивание последней операцией в while. Значит ругается на константу только по указке всевышнего. Пардон. Он не ругается.

Edited by GetSmart

Share this post


Link to post
Share on other sites
Потому как нелогичен такой хак компиляторов.

Как прикольно получается - НЕпризнаение Вами "хаком" использования константы вместо условного выражения привело к "нелогичности" и требованию признать "хаком" while ((c = *ptr++)).

Хотя следует признать, что для однозначности все-же выражение while( x ) тоже по общему счету "хак" и при его запрете единственной формой стала-бы не вызывающая никаких толкований

while( (c = *ptr++) != '\0' ) и никаких вопросов по поводу наличия "лишних" () :).

Share this post


Link to post
Share on other sites
писать "a = b = c" БЕЗ скобок вообще-то позволяет ПРАВИЛО ассоциативности, которое для '=' справа-налево, а не слева-направо, как для, например '=='.
Ну а чуть дальше развить мысль? Что результатом выражения b=c является rvalue, которое в свою очередь может быть вторым операндом оператора "a = ". И этот результат b=c является rvalue без скобок и от добавления скобок ни во что другое не превращается. Читаем еще раз:

Использовано правило по которому выражение с оператором присваивания заключенное в круглые скобки равно присваемому.
Фантазии какие-то. То есть без скобок оно не будет равно присваиваемому? Оказывается - равно. Тогда при чем тут скобки? Или можно цитату из стандарта или хотя бы поминаемого всуе K&R про правило о заключении в скобки?

Не понял. Прямое действие оператора "=" в чём? Действие, не результат. Все операторы должны выполнять какое-то действие над операндами.
В чем прямое действие у оператора '+'? Какое действие он выполняет над операндами? Он возвращает их сумму. Аналогично оператор '=' возвращает значение своего левого операнда после присваивания:

An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue.

Share this post


Link to post
Share on other sites
признать "хаком" while ((c = *ptr++))

Последняя выполненная операция от скобок не меняется. Тип выражения скобки не меняют, а его преобразование в логический тип происходит при встрече самых последних скобок, принадлежащих while. Если rvalue было логическим, то никаких преобразований не требуется. А т.к. логических типов и переменных в Си не существует, то после любого присваивания логического rvalue не будет точно, даже если было. И т.к. while (integer lvalue) и while (integer rvalue) не вызывает ругательств, то наличие присваивания тоже не должно, т.к. даёт такое же состояние - integer rvalue. Ругательство/предупреждение сделано в предположении того, что последнее присваивание есть опечатка. Если в стандарте чёрным по белому написано, что в местах анализа логических rvalue можно применять пару скобок для маскировки этого и только этого предупреждения, тогда всё безупречно. Но эта маскировка не должна происходить из каких-то других правил применения скобок.

 

По поводу константы в условных выражениях цикла стоит закрыть тему. Тухлые помидоры предлагайте в другом месте.

 

Аналогично оператор '=' возвращает значение своего левого операнда после присваивания:

An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue.

Это прямое действие оператора - сохранение. А не побочное. И так же все преобразования rvalue в процессе этого. Например из логического в числовое представление. И "возвращает" неправильный перевод цитаты. Правильнее "выражение будет содержать" значение своего левого операнда после присваивания.

Edited by GetSmart

Share this post


Link to post
Share on other sites

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

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

Таже фигня с ваел 1, если вы в себе не уверены, разрешите компилятору искать такие места, если знаете что делаете убирите разрешение. На то что он плохой или хороший это не влияет. Если он получает бинарь - молодец, нет - не молодец. А прочее это удобство бонусом. По стандарту что делать и как интерпретировать такие выражение описано, и всех делов имхо!

 

Share this post


Link to post
Share on other sites
Фантазии какие-то. То есть без скобок оно не будет равно присваиваемому? Оказывается - равно. Тогда при чем тут скобки?

В приведеном тобой примере НЕ имеющим отношения к обсуждаемому наличие скобок ничего не меняет по причине действия названного мой другого правила.

Но это совершенно не означает, что наличие заключающих скобок для выражения присваивания никогда ничего не меняет.

Что не понятно-то?

Или можно цитату из стандарта или хотя бы поминаемого всуе K&R про правило о заключении в скобки?

Ты откуда взял это выражение с двойными скобками? Я лет 30 назад из K&R - просто другого не было ничего :) и с ТЕХ ПОР ТАК ПИШУ. Сейчас скачал 3 издание, там на вскидку попытался найти но все уже какое-то причесанное под учебник с явными операторами сравнения.

 

 

 

Таже фигня с ваел 1, если вы в себе не уверены

Не надо нести глупости про "неувереность в себе", с ТУПЫМ упрямством сводить все к вырожденному варианту выражения и после чего "удивляться", ну только последний дурак может такую ошибку сделать. Я приводил примеры, в том числе и специально чужой из жизни, когда безмолвное разрешение компилятором абсолютно ни для чего ненужного трюка while( CONST ) приводит к пропуску ошибки. Все, достаточно объяснений - имеющий разум да поймет.

 

Share this post


Link to post
Share on other sites

Имеющий то уже давно понял.

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

Share this post


Link to post
Share on other sites
Вы опять потеряли фокус. Стандарт описывает как из слов получить бинарь. Компилятор делает это по описанному стандартом методу. Все остальное это упражнения для ума. В этом контексте нет разрешений и запретов, есть просто перевод текста в бинарь, алгоритма в программу, по заданным правилам и все...

Нет далеко совсем не все. Этот "перевод" должен быть максимально эффективным и безошибочными. Для этого и надо заниматься и "упражнениями для ума" и добиваться максимального взаимопонимания с компилятором. В противном случае легко и просто получается говнокод, он-же индийский,... - работает как-то иногда и ладно, а что не заработает полезем отладчиком и залатаем. Ну как-же говнокодеру без отладчика, ведь он не знает четко, как им написанное "в бинарь, алгоритма в программу" перевратится и как будет работать. А тут еще некоторые компиляторы всякие предупреждения выдают - у него уже "все работает", и вообще он этот кусок у другого говнокодера из интнеренту взял, а компилятор чего-то там пишет. "Плохой" этот компилятор - нет что-бы просто "перевести в бинарь".

 

А вообще хотелось-бы напомнить с чего все это c while(CONST) началось: http://electronix.ru/forum/index.php?showt...t&p=1361143

Это совершенно бездумный "совет" в котром не только была НЕВЕРНО названа причина использования такого трюка, но и призвано тупо повторять трюк "автоматически" ( автору предлагаю

переписать "правильно" ну хотя-бы банальный макрос MIN( x, y )

#define MIN( X, Y )           \
( {                                  \
   typeof (X) xx = (X);       \
   typeof (Y) yy = (Y);        \
   (xx < yy) ? xx : yy;        \
} )

 

)

Только ведь сей "совет" никого не покоробил, зато ответ, в котором выражение do{...}while(0) было названо трюком, коим оно и является, вызвало бурную реакцию.

 

Не удержался :(. Ладно, теперь уж точно все!

Share this post


Link to post
Share on other sites
А вообще хотелось-бы напомнить с чего все это c while(CONST) началось: http://electronix.ru/forum/index.php?showt...t&p=1361143

Это совершенно бездумный "совет" в котром не только была НЕВЕРНО названа причина использования такого трюка, но и призвано тупо повторять трюк "автоматически" (

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

Edited by Kabdim

Share this post


Link to post
Share on other sites
Что не понятно-то?

Использовано правило по которому выражение с оператором присваивания заключенное в круглые скобки равно присваемому. Просто надо знать и понимать язык.

Тавтология. Отсебятина или из стандарта?

 

Даже больше. Здесь не только зацитировано X==X, но и показано, что наличие скобок в данном примере ничего не меняет. Именно такой смысл у формулировки. Спец по бессмысленности always true должен такую ерунду чуять за версту.

 

Добавление чего-то должно формулироваться в указании отличия. Например, добавление скобок меняет последовательность вычислений операторов. А в данном случае отличие - подтверждение отсутствия опечатки. Что-то мешает внятно писать?

 

Edited by GetSmart

Share this post


Link to post
Share on other sites
...

Ты откуда взял это выражение с двойными скобками? Я лет 30 назад из K&R - просто другого не было ничего :) и с ТЕХ ПОР ТАК ПИШУ. Сейчас скачал 3 издание, там на вскидку попытался найти но все уже какое-то причесанное под учебник с явными операторами сравнения.

...

Тут такое дело...

Код от "Самого" Ритчи: https://github.com/mortdeus/legacy-cc/blob/...120c/c11.c#L219

И не надо фантазировать на пустом месте по поводу скобок.

 

P.S. Так я от Вас и не получил подтверждения Ваших слов про:

"...ибо while(константа) принципиально ошибочное выражение,..."

Получил только очередные фантазии про цикл for(;;), которого ВООБЩЕ не было в первых компилаторах Си. А while был. И автор языка для циклов использовал именно while.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this