Здравствуйте, Qbit86, Вы писали:
Q>Выглядит как UB, и компилятор пользуется своим правом произвола. Вероятно, он просто сгенерировал возврат нуля, задетектив UB.
Здравствуйте, kov_serg, Вы писали:
_>Знатоки стандарта, что вас давно не слышно. Что должна вернуть функция? _>int fn() { int x; return x || !x; }
какая разница что должна вернуть "функция" — если это говнокод и ему не место в нормальном проекте ..
теоретически вообще компилятор может не инициализировать объявляемые таким образом переменные и просто назначить для неё некую ("произвольную") ячейку памяти, в которой могло остаться любое значение (от работы предыдущих программ и т.д.)
но тогда бы да, по идее возвращаемое значение — должно было бы быть равно единице всегда .. значит всё таки компилятор детектит — и возвращает ноль, как Qbit86 и пишет ..
Здравствуйте, Qbit86, Вы писали:
Q>>>Вероятно, он просто сгенерировал возврат нуля, задетектив UB.
Q>Бывает и хуже: https://users.livejournal.com/-winnie/426746.html
Это тоже лютый идиотизм. Вместо добавления модификаторов типа делают так, как будто мы работаем на другой платформе и при этом тоже нарушая логику. Вместо исключения, выкидывая условие выхода из цикла.
_>>Как вы относитесь к такому праву?
Q>Перешёл на C#
Здравствуйте, xma, Вы писали:
xma>какая разница что должна вернуть "функция" — если это говнокод и ему не место в нормальном проекте ..
Есть мнение что это не говонокод. Это говно компилятор.
xma>теоретически вообще компилятор может не инициализировать объявляемые таким образом переменные и просто назначить для неё некую ("произвольную") ячейку памяти, в которой могло остаться любое значение (от работы предыдущих программ и т.д.)
Бл%ть что это за противоречивая теория такая используется?
xma>но тогда бы да, по идее возвращаемое значение — должно было бы быть равно единице всегда .. значит всё таки компилятор детектит — и возвращает ноль, как Qbit86 и пишет ..
Это значит что компилятор содержит лоигескую ошибку и выполняет не допустимые математические преобразования без каких либо доказательств.
Тут явное деление на 0 и компилятор должен просто не скомпилировать этот код. А runtime выкинуть исключение. Но в место этого вы видим разброс и шатания. И всем норм, а главное всё по стандарту
_>От чего может зависеть результат? И почему clang начиная с 5-ой версии считает что 0 будет самый раз?
Хороший и добрый компилятор, а ведь мог и бритвочкой полоснуть диск отформатировать. Имел право.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, kov_serg, Вы писали:
_>Знатоки стандарта, что вас давно не слышно. Что должна вернуть функция? _>
_>int fn() { int x; return x || !x; }
_>
_>От чего может зависеть результат? И почему clang начиная с 5-ой версии считает что 0 будет самый раз?
Возвратит хрень. Потому что используется не инициализированная переменная. Какую хрень — зависит от компилятора. И не нужно искать тут тайные знания.
А написание подобной функции — явный признак крайне низкой квалификации программиста. (если честно — знание правил инициализации ожидается начиная от уровня джуна)
Здравствуйте, AeroSun, Вы писали:
AS>Возвратит хрень. Потому что используется не инициализированная переменная. Какую хрень — зависит от компилятора. И не нужно искать тут тайные знания.
Вы можете аргументировано обосновать эту точку зрения?
AS>А написание подобной функции — явный признак крайне низкой квалификации программиста. (если честно — знание правил инициализации ожидается начиная от уровня джуна)
Это синтетический пример. Реальность гораздо страшнее. Вы не поверите, но программы обычно пишут люди разной квалификации и не в одиночку.
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, AeroSun, Вы писали:
AS>>Возвратит хрень. Потому что используется не инициализированная переменная. Какую хрень — зависит от компилятора. И не нужно искать тут тайные знания. _>Вы можете аргументировано обосновать эту точку зрения?
Да. Это не инициализированная переменная. Работа с ней — UB. Компилятор может хоть 42 возвращать в качестве значения любой операции с ней — это его право.
AS>>А написание подобной функции — явный признак крайне низкой квалификации программиста. (если честно — знание правил инициализации ожидается начиная от уровня джуна) _>Это синтетический пример. Реальность гораздо страшнее. Вы не поверите, но программы обычно пишут люди разной квалификации и не в одиночку.
Это в любом языке так — всегда можно сделать полную дичь. Только в одних языках это видно сразу, другие прячут проблему под ковёр.
В с++, если переменная не инициализирована — код ревью не должен проходить, либо человек должен обосновать отсутствие инициализации.
AS>>А написание подобной функции — явный признак крайне низкой квалификации программиста. (если честно — знание правил инициализации ожидается начиная от уровня джуна) _>Это синтетический пример. Реальность гораздо страшнее. Вы не поверите, но программы обычно пишут люди разной квалификации и не в одиночку.
Тебе о чем и говорят — человек написавший такой код имеет низкую квалификацию, и хорошо что компилятор помог отловить этот баг, вернув ноль.
Ну или pain in the ass, в зависимости от того, каким местом думает юзер.
Ну и вдогонку, если очень хочется щегольнуть обширным интеллектом, то clang умеет выдавать дамп AST, а LLVM — IR после каждого прохода. Если их внимательно покурить, будет сразу понятно, откуда взялся ноль. Но материться в комментариях на ломанном рунглише, конечно, куда интересней.
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?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Потому что имеет на это полное право. А чтоб наглядней было, можно еще вот так: R>https://godbolt.org/z/b44de6h8q R>
R>int fn() { int x; return x == x; }
R>
R>P.S. Тебе уже сто раз все объяснили, но ты продолжаешь упрямствовать. А на чем, собственно, основана твоя уверенность, что правила математики применимы к x?
Чем плохи правила математики? Они не противоречивые. Но тут полная фигня. Любое появления новых правил с потолка приводят к печальным последствиям появлению только костылей. А уж когда на основе таких правил преобразуют код это вообще полный ужас. Можно тушить свет и сливать воду.
Мне не понятно одно: упрямство окружающих с пеной у рта защищающих подобное поведение. Разве не очевидно что подобные правила только умножают скорбь сложность, привнося хаос новые сущности на ровном месте, ничего не давая взамен.
Здравствуйте, kov_serg, Вы писали:
_>Чем плохи правила математики?
А кто говорит, что они плохи? Просто не всегда применимы. Тебя же не удивляет, например, что результат сложения некоторых объектов целых типов не соответствует правилам математики. Или удивляет?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
_>>Чем плохи правила математики?
R>А кто говорит, что они плохи? Просто не всегда применимы. Тебя же не удивляет, например, что результат сложения некоторых объектов целых типов не соответствует правилам математики. Или удивляет?
У меня у целых типов модульная арфметика и поэтому всё строго с правилами. Ломаются правила математики только с целыми типами с насыщением.
А вас не удивляет что в тип пытаются добавить новый элемент, который в этом типе не возможн (не представим) и этим значением ломают все остальные операции для допустимых значений? При этом дальше с подобным значением делают преобразования, которые влияют на резульирующий код, забывая что данное значение не поддреживает никаких преобразований ибо они для него противоречивы.
Здравствуйте, kov_serg, Вы писали:
_>У меня у целых типов модульная арфметика и поэтому всё строго с правилами.
А кого волнует, что там У ТЕБЯ? Правила математики, они не у тебя. И в каких-то прикладных аспектах они работают, в каких-то нет. Нравится тебе это или нет.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>А кого волнует, что там У ТЕБЯ? Правила математики, они не у тебя. И в каких-то прикладных аспектах они работают, в каких-то нет. Нравится тебе это или нет.
Мне это категорически не нравиться. Ибо сличком много исключений из правил так где это совершенно не нужно. И закладывать гавно в фундамент это так себе идея.
Здравствуйте, kov_serg, Вы писали:
_>Мне это категорически не нравиться. Ибо сличком много исключений из правил так где это совершенно не нужно. И закладывать гавно в фундамент это так себе идея.
А закладывать в язык тормознутые памперсы, только ради того, чтоб можно было переменные не инициализировать — такое правильные пацаны не оценят.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>А закладывать в язык тормознутые памперсы, только ради того, чтоб можно было переменные не инициализировать — такое правильные пацаны не оценят.
В каком месте оно тормознутое? Вернуть 1 или 0 по производительности одно и тоже.
Правильные пацаны правильные, потому что правильные пацаны считают их правильными? Математические правила строги и не предвзяты, в отличии от "правильных" пацанов.
Здравствуйте, rg45, Вы писали:
R>Разница в производительности не в возвращаемом значении, а в том, нужно ли расставлять памперсы и развешивать слюнявчики.
Не понятно, раставлять растяжки, капканы, раскидывать саморезы и битое стекло и раскладывать грабли, а не памперсы и слюнявчики. Где тут разница в производительности?
Здравствуйте, kov_serg, Вы писали:
_>Не понятно, раставлять растяжки, капканы, раскидывать саморезы и битое стекло и раскладывать грабли, а не памперсы и слюнявчики. Где тут разница в производительности? _>
сгенерировать исключение или завершить программу, это что, бесплатно по-твоему? Или что ты предлагаешь, сделать вид, что все нормально и вычислить выражение с неинициализированной переменной?
--
Не можешь достичь желаемого — пожелай достигнутого.
сгенерировать исключение или завершить программу, это что, бесплатно по-твоему? Или что ты предлагаешь, сделать вид, что все нормально и вычислить выражение с неинициализированной переменной?
Я бы предложил ошибку компиляции, логично и бесплатно.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, 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, Вы писали:
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" должно быть иначе?
Здравствуйте, 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" должно быть иначе?
— Але, мама, дай папе трубку.
— Але, папа, Спартак чемпион??? ?
— Да, да, да, конечно, дочка, конечно!!! !
— Пап, дай маму.
— Але, мам, ты слышала, папа разрешил.
А почему вы считаете что данное равенство не должно выполняться?
Здравствуйте, B0FEE664, Вы писали:
_>>Нет я полагаю что компилятор оперирует элементом не принадлежащим множеству значений int. BFE>Разумеется. Компилятор работает с текстом.
Он не с текстом работает когда проводит преобразования над DAG-ом. _>>И советую обходить такие компиляторы стороной. BFE>Почему?
Потому что я против наркотиков https://godbolt.org/z/eMeY777T3
Здравствуйте, 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; означает: взять произвольное неопределённое значение и сравнить его с произвольным неопределённым значением. Стоит ли удивляться результату при такой семантике?