Здравствуйте, kov_serg, Вы писали:
_>Знатоки стандарта, что вас давно не слышно. Что должна вернуть функция? _>int fn() { int x; return x || !x; }
какая разница что должна вернуть "функция" — если это говнокод и ему не место в нормальном проекте ..
теоретически вообще компилятор может не инициализировать объявляемые таким образом переменные и просто назначить для неё некую ("произвольную") ячейку памяти, в которой могло остаться любое значение (от работы предыдущих программ и т.д.)
но тогда бы да, по идее возвращаемое значение — должно было бы быть равно единице всегда .. значит всё таки компилятор детектит — и возвращает ноль, как Qbit86 и пишет ..
Здравствуйте, xma, Вы писали:
xma>какая разница что должна вернуть "функция" — если это говнокод и ему не место в нормальном проекте ..
Есть мнение что это не говонокод. Это говно компилятор.
xma>теоретически вообще компилятор может не инициализировать объявляемые таким образом переменные и просто назначить для неё некую ("произвольную") ячейку памяти, в которой могло остаться любое значение (от работы предыдущих программ и т.д.)
Бл%ть что это за противоречивая теория такая используется?
xma>но тогда бы да, по идее возвращаемое значение — должно было бы быть равно единице всегда .. значит всё таки компилятор детектит — и возвращает ноль, как Qbit86 и пишет ..
Это значит что компилятор содержит лоигескую ошибку и выполняет не допустимые математические преобразования без каких либо доказательств.
Здравствуйте, kov_serg, Вы писали:
_>Знатоки стандарта, что вас давно не слышно. Что должна вернуть функция? _>
_>int fn() { int x; return x || !x; }
_>
_>От чего может зависеть результат? И почему clang начиная с 5-ой версии считает что 0 будет самый раз?
Возвратит хрень. Потому что используется не инициализированная переменная. Какую хрень — зависит от компилятора. И не нужно искать тут тайные знания.
А написание подобной функции — явный признак крайне низкой квалификации программиста. (если честно — знание правил инициализации ожидается начиная от уровня джуна)
Здравствуйте, kov_serg, Вы писали:
R>>P.S. Тебе уже сто раз все объяснили, но ты продолжаешь упрямствовать. А на чем, собственно, основана твоя уверенность, что правила математики применимы к x? _>Чем плохи правила математики? Они не противоречивые. Но тут полная фигня. ... _>Мне не понятно одно: упрямство окружающих с пеной у рта защищающих подобное поведение. ...
Не стоит забывать, что выполнение программы на С++ должно следовать правилам абстрактной машины не привязанной ни к какой архитектуре процессора.
Рассмотрим функцию:
int fn() { int x; return x || !x; }
вычисление преобразований 'x в bool' и '!x -> bool' можно выполнить параллельно на двух разных процессорах взяв в качестве значения x произвольное значение для каждого из преобразований. (Это можно сделать, так как преобразование '!x -> bool' не содержит сторонних эффектов.) Если потребовать выполнения правил математики, то для каждого из преобразований произвольное значение x взять нельзя. Тем самым выполнение правил математики потребует дополнительных операций: согласованных инициализаций x произвольным (но одинаковым для параллельно выполняемых операций) значением, а это противоречие принципу языка "не платить за то, что не используется". Поэтому для выполнения преобразований 'x в bool' и для преобразования '!x -> bool' в качестве значения x можно взять произвольное значение для каждого из преобразований. Следовательно результат выполнения может быть произвольным. Поэтому оптимизатор может оптимизировать код до произвольного значения.
Здравствуйте, B0FEE664, Вы писали:
_>>Нет я полагаю что компилятор оперирует элементом не принадлежащим множеству значений int. BFE>Разумеется. Компилятор работает с текстом.
Он не с текстом работает когда проводит преобразования над DAG-ом. _>>И советую обходить такие компиляторы стороной. BFE>Почему?
Потому что я против наркотиков https://godbolt.org/z/eMeY777T3
_>От чего может зависеть результат? И почему clang начиная с 5-ой версии считает что 0 будет самый раз?
Хороший и добрый компилятор, а ведь мог и бритвочкой полоснуть диск отформатировать. Имел право.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, AeroSun, Вы писали:
AS>Возвратит хрень. Потому что используется не инициализированная переменная. Какую хрень — зависит от компилятора. И не нужно искать тут тайные знания.
Вы можете аргументировано обосновать эту точку зрения?
AS>А написание подобной функции — явный признак крайне низкой квалификации программиста. (если честно — знание правил инициализации ожидается начиная от уровня джуна)
Это синтетический пример. Реальность гораздо страшнее. Вы не поверите, но программы обычно пишут люди разной квалификации и не в одиночку.
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, AeroSun, Вы писали:
AS>>Возвратит хрень. Потому что используется не инициализированная переменная. Какую хрень — зависит от компилятора. И не нужно искать тут тайные знания. _>Вы можете аргументировано обосновать эту точку зрения?
Да. Это не инициализированная переменная. Работа с ней — UB. Компилятор может хоть 42 возвращать в качестве значения любой операции с ней — это его право.
AS>>А написание подобной функции — явный признак крайне низкой квалификации программиста. (если честно — знание правил инициализации ожидается начиная от уровня джуна) _>Это синтетический пример. Реальность гораздо страшнее. Вы не поверите, но программы обычно пишут люди разной квалификации и не в одиночку.
Это в любом языке так — всегда можно сделать полную дичь. Только в одних языках это видно сразу, другие прячут проблему под ковёр.
В с++, если переменная не инициализирована — код ревью не должен проходить, либо человек должен обосновать отсутствие инициализации.
Ну или pain in the ass, в зависимости от того, каким местом думает юзер.
Ну и вдогонку, если очень хочется щегольнуть обширным интеллектом, то clang умеет выдавать дамп AST, а LLVM — IR после каждого прохода. Если их внимательно покурить, будет сразу понятно, откуда взялся ноль. Но материться в комментариях на ломанном рунглише, конечно, куда интересней.
Здравствуйте, rg45, Вы писали:
R>Потому что имеет на это полное право. А чтоб наглядней было, можно еще вот так: R>https://godbolt.org/z/b44de6h8q R>
R>int fn() { int x; return x == x; }
R>
R>P.S. Тебе уже сто раз все объяснили, но ты продолжаешь упрямствовать. А на чем, собственно, основана твоя уверенность, что правила математики применимы к x?
Чем плохи правила математики? Они не противоречивые. Но тут полная фигня. Любое появления новых правил с потолка приводят к печальным последствиям появлению только костылей. А уж когда на основе таких правил преобразуют код это вообще полный ужас. Можно тушить свет и сливать воду.
Мне не понятно одно: упрямство окружающих с пеной у рта защищающих подобное поведение. Разве не очевидно что подобные правила только умножают скорбь сложность, привнося хаос новые сущности на ровном месте, ничего не давая взамен.
сгенерировать исключение или завершить программу, это что, бесплатно по-твоему? Или что ты предлагаешь, сделать вид, что все нормально и вычислить выражение с неинициализированной переменной?
Я бы предложил ошибку компиляции, логично и бесплатно.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, B0FEE664, Вы писали:
BFE>Здесь ровно тоже самое: x слева и x справа не обязаны иметь одно и тоже значение.
Если у меня переменная не volatile почему она имеет не одно и тоже значение?
BFE>Скажите, kov_serg, а вы понимаете, что в выражении: BFE>x = 1 + x BFE>значения x слева и x справа имеют разные значения?
Тут операция явного изменения значения переменной x. Как это связано с последующим вопросом?
В erlang если переменной присвоили значение, то всё оно не меняется. А тут даже если оно не меняется оно не совпадает само с собой.
#include <stdio.h>
bool fn() {
int x;
const int z=x;
return z==z;
}
int main() {
if (fn()) printf("always true\n");
else printf("not true\n");
}
<source>:6:13: warning: self-comparison always evaluates to true [-Wtautological-compare]
return z==z;
^
1 warning generated.
Execution build compiler returned: 0
Program returned: 0
not true
Так же возвращает false
BFE>Если ответ "да", то почему вы предполагаете, что в выражении "x==x" должно быть иначе?
— Але, мама, дай папе трубку.
— Але, папа, Спартак чемпион??? ?
— Да, да, да, конечно, дочка, конечно!!! !
— Пап, дай маму.
— Але, мам, ты слышала, папа разрешил.
А почему вы считаете что данное равенство не должно выполняться?
Здравствуйте, Qbit86, Вы писали:
Q>Выглядит как UB, и компилятор пользуется своим правом произвола. Вероятно, он просто сгенерировал возврат нуля, задетектив UB.
Здравствуйте, Qbit86, Вы писали:
Q>>>Вероятно, он просто сгенерировал возврат нуля, задетектив UB.
Q>Бывает и хуже: https://users.livejournal.com/-winnie/426746.html
Это тоже лютый идиотизм. Вместо добавления модификаторов типа делают так, как будто мы работаем на другой платформе и при этом тоже нарушая логику. Вместо исключения, выкидывая условие выхода из цикла.
_>>Как вы относитесь к такому праву?
Q>Перешёл на C#
Тут явное деление на 0 и компилятор должен просто не скомпилировать этот код. А runtime выкинуть исключение. Но в место этого вы видим разброс и шатания. И всем норм, а главное всё по стандарту
AS>>А написание подобной функции — явный признак крайне низкой квалификации программиста. (если честно — знание правил инициализации ожидается начиная от уровня джуна) _>Это синтетический пример. Реальность гораздо страшнее. Вы не поверите, но программы обычно пишут люди разной квалификации и не в одиночку.
Тебе о чем и говорят — человек написавший такой код имеет низкую квалификацию, и хорошо что компилятор помог отловить этот баг, вернув ноль.
Q>Ну и вдогонку, если очень хочется щегольнуть обширным интеллектом, то clang умеет выдавать дамп AST, а LLVM — IR после каждого прохода. Если их внимательно покурить, будет сразу понятно, откуда взялся ноль. Но материться в комментариях на ломанном рунглише, конечно, куда интересней.
Ну это же kov_serg он любит ходить с шарманкой (про плохой С++) по дворам как болгарин с обезъяной.
Здравствуйте, kov_serg, Вы писали:
_>Знатоки стандарта, что вас давно не слышно. Что должна вернуть функция? _>int fn() { int x; return x || !x; } _>От чего может зависеть результат? И почему clang начиная с 5-ой версии считает что 0 будет самый раз?
Типичная ошибка, считать что программа прочитает случайное значение, и затем начнет его использовать в вычислениях.
Знаменитая кляуза стандарта "при наличии UB все гарантии отменяются" по сути является разрешением оптимизатору исходить из предположения, что UB в программе никогда не будет исполнено. Это значит что когда UB есть, то "ошибки" оптимизации вызванные его наличием, по определению не ошибки, и исправлять их авторы оптимизатора не обязаны.
В данном случае логика: если чтение `x` это UB, но UB никогда не будет исполнено, значит `x || !x` никогда не будет исполнено. Если оно никогда не будет исполнено, значит это мертвый код, и его можно выкинуть. Не знаю, откуда берется конкретно 0, может это просто какое-то значение по умолчанию внутри оптимизатора, но разгадка именно в этом: ты считаешь, что `x` будет прочитано, а на самом деле весь код, трогающий `x` был выкинут оптимизатором как "невозможный" еще при компиляции. В чем легко убедиться, добавив аргумент `'-Rpass=.*'` и отметив что код функции fn() был сокращен до 0 байт.
Тут надо отметить, далеко не все согласны, что стоит давать оптимизатору столько свободы, хотя бы просто потому, что 99% программ в реальном мире хотя бы иногда исполняют UB. Но пока что оно так.
Здравствуйте, 5.März, Вы писали:
5M>Типичная ошибка, считать что программа прочитает случайное значение, и затем начнет его использовать в вычислениях.
Принцип наименьшего удивления в C++ не применяется. Всё что компилятор делает через жопу, но с одобрения стандарта считается нормальным, а виноват именно человек который этот компилятор использовал.
5M>Знаменитая кляуза стандарта "при наличии UB все гарантии отменяются" по сути является разрешением оптимизатору исходить из предположения, что UB в программе никогда не будет исполнено. Это значит что когда UB есть, то "ошибки" оптимизации вызванные его наличием, по определению не ошибки, и исправлять их авторы оптимизатора не обязаны.
5M>В данном случае логика: если чтение `x` это UB, но UB никогда не будет исполнено, значит `x || !x` никогда не будет исполнено. Если оно никогда не будет исполнено, значит это мертвый код, и его можно выкинуть. Не знаю, откуда берется конкретно 0, может это просто какое-то значение по умолчанию внутри оптимизатора, но разгадка именно в этом: ты считаешь, что `x` будет прочитано, а на самом деле весь код, трогающий `x` был выкинут оптимизатором как "невозможный" еще при компиляции. В чем легко убедиться, добавив аргумент `'-Rpass=.*'` и отметив что код функции fn() был сокращен до 0 байт.
Так оно и ясно он x присваивает значение undefined для него математичесие операции определены частично и не согласованно, на пример undefined+undefined = 0, undefined*0=0, undefined&non_zero=0, undefined|non_zero=-1, undefined<=undefined=0, undefined==undefined=0, undefined!=undefined=0 ...
Для выражения x||!x он делает undefined || !undefined = undefined и потом undefined преобразует в 0.
Претензии именно в таком идиотском поведении, нельзя использовать элементы множества которые не принадлежат исходному множеству, более того действовать по правилам которые никакого отношения к исходным правилам не имеют. Компилятор тут смешивает мягкое с тёплым и потом преобразует в число.
5M>Тут надо отметить, далеко не все согласны, что стоит давать оптимизатору столько свободы, хотя бы просто потому, что 99% программ в реальном мире хотя бы иногда исполняют UB. Но пока что оно так.
Дело в том что свободу компилятору то дают, а вот ответственности никакой.
Здравствуйте, ·, Вы писали:
M>> что 99% программ в реальном мире хотя бы иногда исполняют UB. ·>??? Это почему?
Креши и уязвимости есть в любом более-менее большом проекте, они практически всегда связаны с UB. Да не всякий UB вызывает видимый баг, иногда все пролетает незаметно. В ядре Linux его постоянно находят и находят в новых местах, в популярном софте и т.д. Иногда даже в коде который 20 лет стабильно работал и не менялся типа zlib. Баги, вызывающие UB, это де-факто норма в индустрии.
Если погуглить "optimization-unstable code" найдешь много статей с критикой такого подхода к оптимизации при наличии UB.
Здравствуйте, σ, Вы писали:
_>>Претензии именно в таком идиотском поведении, нельзя использовать элементы множества которые не принадлежат исходному множеству
σ>Indeterminate value принадлежит множеству значений (почти (возможно, decltype(nullptr) это исключение)) любого скалярного типа.
Мнимые единицы, и коричневый цвет тоже принадлежит этому множеству? Они тоже скалярные величины.
Нельзя расширять множество чем попало. Если до этого у множества были определены операции над элементами этого множества и новый элемент эти операции ломает, то такое новое множество со старым будет связано чуть более чем никак.
_>>>Претензии именно в таком идиотском поведении, нельзя использовать элементы множества которые не принадлежат исходному множеству
σ>>Indeterminate value принадлежит множеству значений (почти (возможно, decltype(nullptr) это исключение)) любого скалярного типа. _>Мнимые единицы, и коричневый цвет тоже принадлежит этому множеству? Они тоже скалярные величины. _>Нельзя расширять множество чем попало. Если до этого у множества были определены операции над элементами этого множества и новый элемент эти операции ломает
Не ломает, т.к. чтение indeterminate value обычно триггерит UB.
Здравствуйте, σ, Вы писали:
σ>>>Indeterminate value принадлежит множеству значений (почти (возможно, decltype(nullptr) это исключение)) любого скалярного типа. _>>Мнимые единицы, и коричневый цвет тоже принадлежит этому множеству? Они тоже скалярные величины. _>>Нельзя расширять множество чем попало. Если до этого у множества были определены операции над элементами этого множества и новый элемент эти операции ломает
σ>Не ломает, т.к. чтение indeterminate value обычно триггерит UB.
Вы сами себя слышите.
Если бы оно вызывало исключение и завершение программы. Никаких претензий. Но оно возвращает 0.
Посмотрите другой пример с unsigned
unsigned не содержит не определенных поведений (в отличии от int) при сложении с любым другим unsigned, то есть не ub. но u undefined и если так то это может быть либо любое значение в памяти/регистре или исключение при обращении. Но выбираются такие правила, которые этому не соответствуют.
σ>>>>Indeterminate value принадлежит множеству значений (почти (возможно, decltype(nullptr) это исключение)) любого скалярного типа. _>>>Мнимые единицы, и коричневый цвет тоже принадлежит этому множеству? Они тоже скалярные величины. _>>>Нельзя расширять множество чем попало. Если до этого у множества были определены операции над элементами этого множества и новый элемент эти операции ломает
σ>>Не ломает, т.к. чтение indeterminate value обычно триггерит UB. _>Вы сами себя слышите. _>Если бы оно вызывало исключение и завершение программы. Никаких претензий. Но оно возвращает 0.
Неопределённое поведение. Может происходить что угодно.
_>Посмотрите другой пример с unsigned _>
σ>Неопределённое поведение. Может происходить что угодно.
Обосновать можете? Или оно верно потому что оно верно, а если не верно смотри пункт 1.
σ>Чтение объекта тип unsigned, содержащего indeterminate value это такое же UB, как чтение объекта типа int.
Это нарушение правил математики. Которое приводит к не правильным результатам, оправдывается стандартом, при этом вся вина сваливается на программиста.
σ>>Неопределённое поведение. Может происходить что угодно. _>Обосновать можете? Или оно верно потому что оно верно, а если не верно смотри пункт 1.
σ>>Чтение объекта тип unsigned, содержащего indeterminate value это такое же UB, как чтение объекта типа int. _>Это нарушение правил математики. Которое приводит к не правильным результатам, оправдывается стандартом, при этом вся вина сваливается на программиста.
Здравствуйте, σ, Вы писали:
σ>>>Неопределённое поведение. Может происходить что угодно. _>>Обосновать можете? Или оно верно потому что оно верно, а если не верно смотри пункт 1.
σ>>>Чтение объекта тип unsigned, содержащего indeterminate value это такое же UB, как чтение объекта типа int. _>>Это нарушение правил математики. Которое приводит к не правильным результатам, оправдывается стандартом, при этом вся вина сваливается на программиста.
σ>Каких именно «правил математики»?
например этого a-a=0
σ>>>>Неопределённое поведение. Может происходить что угодно. _>>>Обосновать можете? Или оно верно потому что оно верно, а если не верно смотри пункт 1.
σ>>>>Чтение объекта тип unsigned, содержащего indeterminate value это такое же UB, как чтение объекта типа int. _>>>Это нарушение правил математики. Которое приводит к не правильным результатам, оправдывается стандартом, при этом вся вина сваливается на программиста.
σ>>Каких именно «правил математики»? _>например этого a-a=0
И чо, для `a` == `*(volatile int*)0` тоже должно работать?
Здравствуйте, σ, Вы писали:
σ>>>Каких именно «правил математики»? _>>например этого a-a=0
σ>И чо, для `a` == `*(volatile int*)0` тоже должно работать?
Где в объявлении unsigned a; есть указание на *(unsigned volatile*)0 ?
Здравствуйте, Voivoid, Вы писали:
V>Здравствуйте, kov_serg, Вы писали:
σ>>>Каких именно «правил математики»? _>>например этого a-a=0
V>Но, скажем, не при a = 1/0. Так же как и в C++ с не инициализированной a
Значение 1/0 не представимо в рамках типа unsigned, а значит туда его не засунуть никак, совсем никак, вообще никак.
При делении на 0 обычно прерывают исполнения сигналом DIVIDE_BY_ZERO.
σ>>>>Каких именно «правил математики»? _>>>например этого a-a=0
σ>>И чо, для `a` == `*(volatile int*)0` тоже должно работать? _>Где в объявлении unsigned a; есть указание на *(unsigned volatile*)0 ?
А почему закон не должен выполняться для любого `a` (нужного типа)?
Здравствуйте, kov_serg, Вы писали:
V>>Но, скажем, не при a = 1/0. Так же как и в C++ с не инициализированной a _>Значение 1/0 не представимо в рамках типа unsigned, а значит туда его не засунуть никак, совсем никак, вообще никак.
Так я про математику и «правила математики». a-a=0 допустимо не для всех a. Поэтому не вижу особо ничего удивительно, что и в c++ a-a==0 допустимо не для всех значений переменной a
Здравствуйте, Voivoid, Вы писали:
_>>Значение 1/0 не представимо в рамках типа unsigned, а значит туда его не засунуть никак, совсем никак, вообще никак. V>Так я про математику и «правила математики». a-a=0 допустимо не для всех a. Поэтому не вижу особо ничего удивительно, что и в c++ a-a==0 допустимо не для всех значений переменной a
Удивительно потому что unsigned не содержит таких значений. double содержит inf,-0,nan, но unsigned нет. И для всех элементов представимых типом unsigned "a-a" всегда 0
Здравствуйте, σ, Вы писали:
σ>>>И чо, для `a` == `*(volatile int*)0` тоже должно работать? _>>Где в объявлении unsigned a; есть указание на *(unsigned volatile*)0 ?
σ>А почему закон не должен выполняться для любого `a` (нужного типа)?
Переформулируйте вопрос. Что такое нужный тип и кто такой любой a, и какой закон не должен выполняться?
Здравствуйте, kov_serg, Вы писали:
_>Удивительно потому что unsigned не содержит таких значений. double содержит inf,-0,nan, но unsigned нет. И для всех элементов представимых типом unsigned "a-a" всегда 0
Это уже только на некоторой целевой платформе, в runtime, unsigned переменная будет представлена набором бит, все комбинации из которых имеют какое-либо числовое значение. Но в семантике языка c++, в compile time, переменная unsigned кроме этих значений можеть иметь еще и, как уже ранее упоминалось, значение indeterminate.
_>>Удивительно потому что unsigned не содержит таких значений. double содержит inf,-0,nan, но unsigned нет. И для всех элементов представимых типом unsigned "a-a" всегда 0 V>Это уже только на некоторой целевой платформе, в runtime, unsigned переменная будет представлена набором бит, все комбинации из которых имеют какое-либо числовое значение. Но в семантике языка c++, в compile time, переменная unsigned кроме этих значений можеть иметь еще и, как уже ранее упоминалось, значение indeterminate.
Свидитель секты «у объекта не может быть больше значений, чем различных битовых паттернов в его value representation»?
Здравствуйте, 5.März, Вы писали:
M> ·>??? Это почему? M> Креши и уязвимости есть в любом более-менее большом проекте, они практически всегда связаны с UB.
Не очень ясно причём тут оптимизатор. Тут сама философия того, что в C/C++ так много UB. Было бы лучше в спеке языка обозначить, что UB — ошибка компиляции. Но я затрудняюсь предсказать последствия такого.. проще уж другой язык взять.
Правда UB это следствие другой философии — не делать лишнего.
Здравствуйте, ·, Вы писали:
·>Было бы лучше в спеке языка обозначить, что UB — ошибка компиляции. Но я затрудняюсь предсказать последствия такого.. проще уж другой язык взять.
UB не может быть ошибкой компиляции когда есть позволенный стандартом способ скомпилировать без UB. О том весь и сыр-бор насчет optimization-unsafe code.
Здравствуйте, 5.März, Вы писали:
5M>·>Было бы лучше в спеке языка обозначить, что UB — ошибка компиляции. Но я затрудняюсь предсказать последствия такого.. проще уж другой язык взять.
5M>UB не может быть ошибкой компиляции когда есть позволенный стандартом способ скомпилировать без UB. О том весь и сыр-бор насчет optimization-unsafe code.
Почему не может? В той же java такой код будет ошибкой компиляции, по стандарту. Причём тут оптимизации?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, kov_serg, Вы писали:
Q>>Выглядит как UB, и компилятор пользуется своим правом произвола. Вероятно, он просто сгенерировал возврат нуля, задетектив UB.
_>Как вы относитесь к такому праву?
Это инженерный компромисс между быстродействием и безопасностью. C++ позиционируется как "быстрый язык". Если же нужно кидать вэлью лопатами, java/C# будут лучшим выбором.
подразумевалось что constexpr хороший ub занитайзер
а с учетом того что сейчас constexpr натягивают на все
уже и на class base constexpr судя по новым отчетам с меил лист, то про ill formed можно будет вообще забыть в скором будущем
P.S. Тебе уже сто раз все объяснили, но ты продолжаешь упрямствовать. А на чем, собственно, основана твоя уверенность, что правила математики применимы к x?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, kov_serg, Вы писали:
_>Чем плохи правила математики?
А кто говорит, что они плохи? Просто не всегда применимы. Тебя же не удивляет, например, что результат сложения некоторых объектов целых типов не соответствует правилам математики. Или удивляет?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
_>>Чем плохи правила математики?
R>А кто говорит, что они плохи? Просто не всегда применимы. Тебя же не удивляет, например, что результат сложения некоторых объектов целых типов не соответствует правилам математики. Или удивляет?
У меня у целых типов модульная арфметика и поэтому всё строго с правилами. Ломаются правила математики только с целыми типами с насыщением.
А вас не удивляет что в тип пытаются добавить новый элемент, который в этом типе не возможн (не представим) и этим значением ломают все остальные операции для допустимых значений? При этом дальше с подобным значением делают преобразования, которые влияют на резульирующий код, забывая что данное значение не поддреживает никаких преобразований ибо они для него противоречивы.
Здравствуйте, kov_serg, Вы писали:
_>У меня у целых типов модульная арфметика и поэтому всё строго с правилами.
А кого волнует, что там У ТЕБЯ? Правила математики, они не у тебя. И в каких-то прикладных аспектах они работают, в каких-то нет. Нравится тебе это или нет.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>А кого волнует, что там У ТЕБЯ? Правила математики, они не у тебя. И в каких-то прикладных аспектах они работают, в каких-то нет. Нравится тебе это или нет.
Мне это категорически не нравиться. Ибо сличком много исключений из правил так где это совершенно не нужно. И закладывать гавно в фундамент это так себе идея.
Здравствуйте, kov_serg, Вы писали:
_>Мне это категорически не нравиться. Ибо сличком много исключений из правил так где это совершенно не нужно. И закладывать гавно в фундамент это так себе идея.
А закладывать в язык тормознутые памперсы, только ради того, чтоб можно было переменные не инициализировать — такое правильные пацаны не оценят.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>А закладывать в язык тормознутые памперсы, только ради того, чтоб можно было переменные не инициализировать — такое правильные пацаны не оценят.
В каком месте оно тормознутое? Вернуть 1 или 0 по производительности одно и тоже.
Правильные пацаны правильные, потому что правильные пацаны считают их правильными? Математические правила строги и не предвзяты, в отличии от "правильных" пацанов.
Здравствуйте, rg45, Вы писали:
R>Разница в производительности не в возвращаемом значении, а в том, нужно ли расставлять памперсы и развешивать слюнявчики.
Не понятно, раставлять растяжки, капканы, раскидывать саморезы и битое стекло и раскладывать грабли, а не памперсы и слюнявчики. Где тут разница в производительности?
Здравствуйте, kov_serg, Вы писали:
_>Не понятно, раставлять растяжки, капканы, раскидывать саморезы и битое стекло и раскладывать грабли, а не памперсы и слюнявчики. Где тут разница в производительности? _>
сгенерировать исключение или завершить программу, это что, бесплатно по-твоему? Или что ты предлагаешь, сделать вид, что все нормально и вычислить выражение с неинициализированной переменной?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, B0FEE664, Вы писали:
BFE>Не стоит забывать, что выполнение программы на С++ должно следовать правилам абстрактной машины не привязанной ни к какой архитектуре процессора. BFE>Рассмотрим функцию: BFE>
BFE>int fn() { int x; return x || !x; }
BFE>
BFE>вычисление преобразований 'x в bool' и '!x -> bool' можно выполнить параллельно на двух разных процессорах взяв в качестве значения x произвольное значение для каждого из преобразований. (Это можно сделать, так как преобразование '!x -> bool' не содержит сторонних эффектов.) Если потребовать выполнения правил математики, то для каждого из преобразований произвольное значение x взять нельзя. Тем самым выполнение правил математики потребует дополнительных операций: согласованных инициализаций x произвольным (но одинаковым для параллельно выполняемых операций) значением, а это противоречие принципу языка "не платить за то, что не используется". Поэтому для выполнения преобразований 'x в bool' и для преобразования '!x -> bool' в качестве значения x можно взять произвольное значение для каждого из преобразований. Следовательно результат выполнения может быть произвольным. Поэтому оптимизатор может оптимизировать код до произвольного значения.
BFE>Так понятно?
Нет. Без сферы Блоха объяснение не выдерживает никакой критики.
Здравствуйте, kov_serg, Вы писали:
BFE>>Рассмотрим функцию: BFE>>
BFE>>int fn() { int x; return x || !x; }
BFE>>
BFE>>Так понятно? _>Нет. Без сферы Блоха объяснение не выдерживает никакой критики.
А! Я понял ваши затруднения: вы ошибочно полагаете, что в выражении x || !x;x слева и x справа обязаны иметь одно и тоже значение. Так?
Здравствуйте, B0FEE664, Вы писали:
BFE>>>Так понятно? _>>Нет. Без сферы Блоха объяснение не выдерживает никакой критики. BFE>А! Я понял ваши затруднения: вы ошибочно полагаете, что в выражении x || !x;x слева и x справа обязаны иметь одно и тоже значение. Так?
Нет я полагаю что компилятор оперирует элементом не принадлежащим множеству значений int. И советую обходить такие компиляторы стороной.
Как говорит народная мудрость: ложка говна на бочку мёда даёт бочку говна.
Предлагаю объяснить более простой случай: https://godbolt.org/z/4hvzrYq8b можно с обрядами, танцами, злыми духами и туннельными эффектами.
#include <stdio.h>
bool fn() { int x; return x==x; }
int main() {
if (fn()) printf("always true\n");
else printf("not true\n");
}
ASM generation compiler returned: 0
<source>:3:28: warning: self-comparison always evaluates to true [-Wtautological-compare]
bool fn() { int x; return x==x; }
^
1 warning generated.
Execution build compiler returned: 0
Program returned: 0
not true
Здравствуйте, kov_serg, Вы писали:
BFE>>А! Я понял ваши затруднения: вы ошибочно полагаете, что в выражении x || !x;x слева и x справа обязаны иметь одно и тоже значение. Так? _>Нет я полагаю что компилятор оперирует элементом не принадлежащим множеству значений int.
Разумеется. Компилятор работает с текстом. _>И советую обходить такие компиляторы стороной.
Почему?
_>Как говорит народная мудрость: ложка говна на бочку мёда даёт бочку говна.
Тут ведь как: есть люди, которые если чего-то не понимают, то пытаются связать то, что они не понимают с негативными эмоциями для выражения своего отношения. Это проистекает из социальной структуры человеческого общества, а не из знаний, поэтому я не буду следовать по пути таких рассуждений.
_>Предлагаю объяснить более простой случай: https://godbolt.org/z/4hvzrYq8b можно с обрядами, танцами, злыми духами и туннельными эффектами. _>[ccode] _>bool fn() { int x; return x==x; } _>[/code]
Здесь ровно тоже самое: x слева и x справа не обязаны иметь одно и тоже значение.
Скажите, kov_serg, а вы понимаете, что в выражении: x = 1 + x
значения x слева и x справа имеют разные значения?
Если ответ "да", то почему вы предполагаете, что в выражении "x==x" должно быть иначе?
Здравствуйте, kov_serg, Вы писали:
BFE>>Если ответ "да", то почему вы предполагаете, что в выражении "x==x" должно быть иначе? _>А почему вы считаете что данное равенство не должно выполняться?
Потому что никто не обещает, что выражение х вообще должно во что-то вычислиться, а не отформатировать винчестер, например. Но даже если по счастливой случайности оно и вычислится, никто не обещает, что при каждом вычислении значения будут одинаковыми. Твои ожидания относительно значений неинициализированных переменных ни на чем не основаны.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Потому что никто не обещает, что выражение х вообще должно во что-то вычислиться, а не отформатировать винчестер, например. Но даже если по счастливой случайности оно и вычислится, никто не обещает, что при каждом вычислении значения будут одинаковыми.
В каких ещё языках кроме C/C++ есть подобные практики?
Здравствуйте, rg45, Вы писали:
_>>В каких ещё языках кроме C/C++ есть подобные практики? R>У каждого языка есть свои слабые и сильные стороны и если уж сравнивать, то по совокупности. Иначе это просто беспредметный разговор.
Это не слабые стороны — это глупость.
Повторю есть ли еще языки программирования с такими идиотскими "чудными" правилами?
Здравствуйте, kov_serg, Вы писали:
R>>У каждого языка есть свои слабые и сильные стороны и если уж сравнивать, то по совокупности. Иначе это просто беспредметный разговор. _>Это не слабые стороны — это глупость.
Это только на первый взгляд так кажется.
_>Повторю есть ли еще языки программирования с такими идиотскими "чудными" правилами?
А есть ли ещё языки программирования с таким быстрым результирующим кодом?
Здравствуйте, kov_serg, Вы писали:
BFE>>Здесь ровно тоже самое: x слева и x справа не обязаны иметь одно и тоже значение. _>Если у меня переменная не volatile почему она имеет не одно и тоже значение? Всё потому же
.
BFE>>Скажите, kov_serg, а вы понимаете, что в выражении: BFE>>x = 1 + x BFE>>значения x слева и x справа имеют разные значения? _>Тут операция явного изменения значения переменной x. Как это связано с последующим вопросом? BFE>>Если ответ "да", то почему вы предполагаете, что в выражении "x==x" должно быть иначе? _>А почему вы считаете что данное равенство не должно выполняться?
Смотрите, с точки зрения математики не существует такого x, что x = 1 + x. Вы, однако, понимаете, что "Тут операция явного изменения значения переменной x.". Следовательно то, что понимается под x в программировании — это не тоже самое, что понимается под х в математике. Это совершенно разные по семантике записи не смотря на то, что по синтаксису они похожи. В частности, x == x — это никакое не равенство. Это операция сравнения. Программа вида int x; return x == x; означает: взять произвольное неопределённое значение и сравнить его с произвольным неопределённым значением. Стоит ли удивляться результату при такой семантике?