Здравствуйте Павел Кузнецов, Вы писали:
ПК>До TC уже недолго осталось: Andrew Koenig где-то говорил, что уже подали в ISO, стало быть где-то в районе нескольких месяцев – года до публикации. В любом случае, следующая версия стандарта ожидается где-то к 2008 или около того — не так уж и долго по вселенским меркам
ТС = тот свет?
В общем, можно поздравить: С++ достаточно высокоорганизован, чтобы попасть под теорему Гёделя.
Оказывается, в нём есть выражения, про которые даже нельзя сказать, undefined они или нет!
И кто бы подумал, что одно из них — банальное x=y=0
Слава богу, что компиляторы на таких философских вопросах не застревают, а тихо делают своё чёрное дело.
Пойду пить безалкогольное , а то совсем башню оторвёт. Никому нельзя верить.
Здравствуйте Кодт, Вы писали:
ПК>>До TC уже недолго осталось: Andrew Koenig где-то говорил, что уже подали в ISO, стало быть где-то в районе нескольких месяцев – года до публикации. <...>
К>ТС = тот свет? :???:
Technical Corrigenda, содержит исправления ошибок, найденных в стандарте, может выпускаться чаще, чем новые версии последнего.
К>В общем, можно поздравить: С++ достаточно высокоорганизован, чтобы попасть под теорему Гёделя.
Под теоремы Геделя подпадают любые логические системы, использующие арифметику.
К>Оказывается, в нём есть выражения, про которые даже нельзя сказать, undefined они или нет! :beer:
То же относится и к любому другому языку. Undefined behavior во многих случаях определяется в период выполнения.
К>И кто бы подумал, что одно из них — банальное x=y=0 :wow:
Только в том случае, если x и y являются именами одного и того же объекта.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[10]: Чудеса инкремента...
От:
Аноним
Дата:
04.09.02 16:15
Оценка:
Здравствуйте Кодт, Вы писали:
К>В общем, можно поздравить: С++ достаточно высокоорганизован, чтобы попасть под теорему Гёделя. К>Оказывается, в нём есть выражения, про которые даже нельзя сказать, undefined они или нет! К>И кто бы подумал, что одно из них — банальное x=y=0
C++ очень сложный язык — даже авторы стандарта его не знают. Но только это и позволило ему стать языком номер один.
К>Пойду пить безалкогольное , а то совсем башню оторвёт. Никому нельзя верить.
Небольшое лирическое отступление. Меня здесь все бросились критиковать и пинать ногами это хорошо! Значит мы доберемся до истины (если это сейчас возможно, хотя видимо пока невозможно), а то форум стал превращаться в погоню за баллами, когда мнения людей из топа не оспариваются, а с ними молча соглашаются и ставят баллы. Мне это мало интересно, мне интересно узнавать что-то новое. Чем больше изучаешь С++ тем больше понимаешь, что всего знать нельзя и не ошибаться тоже нельзя, С++ лишком большой и ты всегда чего-то не знаешь или думаешь, что знаешь, но ошибаешься. Поэтому я доволен, когда я ошибаюсь и меня поправляют – значит я узнаю что-то новое или восполняю пробелы, чтобы следующий раз не ошибаться. Могу сказать, что даже Страуструп не всегда бывает прав, правде если он бывает не прав, то обычно исправляют стандарт
Теперь по делу. То, о чем мы спорим однозначного решения пока не имеет, об этом еще дискутируют в комитете по стандартизации С++ http://www.dkuug.dk/jtc1/sc22/wg21. Достаточно посмотреть две темы 222 Sequence points and lvalue-returning operators и 351 Sequence point error: unspecified or undefined?. Первая в состоянии drafting, а вторая вообще в состоянии open. В 222 теме примеры аналогичные моим – типа i = i = 0, предлагаемое решение добавление точки следования в операторе присваивания. Про 351 нет даже предварительного мнения, когда оно будет тогда и будем говорить undefined или unspecified, пока я вижу двухкратное упоминание unspecified, и однократное undefined, так что с математической точки зрения вероятнее, что опечатка undefined.
Здравствуйте dupamid, Вы писали:
D>Теперь по делу. То, о чем мы спорим однозначного решения пока не имеет,
Прежде всего давай определимся, о чем идет речь. Я утверждаю, что согласно текущей редакции стандарта модификация скалярных объектов более одного раза между соседними точками следования приводит к неопределенному поведению программы. Если ты споришь с этим, то продолжаем, иначе, пожалуйста, сформулируй свою позицию.
D>об этом еще дискутируют в комитете по стандартизации С++ http://www.dkuug.dk/jtc1/sc22/wg21. Достаточно посмотреть две темы 222 Sequence points and lvalue-returning operators и 351 Sequence point error: unspecified or undefined?. Первая в состоянии drafting, а вторая вообще в состоянии open.
В 222 подтверждается, что в текущей редакции стандарта — основной нормативный документ для разрешения подобных разногласий — конструкции вида (a += b) += c; приводят к неопределенному поведению. С другой стороны, утверждается, что подобные конструкции могут быть полезны и для этого предлагается изменить существующую спецификацию, причем не в той части, которая вызвала разногласия. Кроме того, уточняются некоторые формулировки относительно случаев типа x = y = 0. Но это уже все совсем другие "пироги".
D>предлагаемое решение добавление точки следования в операторе присваивания.
Это не разрешение (несуществующей) неоднозначности, это изменение существующей спецификации, к предмету разговора никакого отношения не имеющее. Когда все операции присваивания, в т.ч. и "простые", будут сопровождаться точками следования, тогда некоторые из приводимых тобой примеров станут примерами не установленного (unspecified behavior), а некоторые и вовсе приобретут точно определенное поведение. Однако это никоим образом не влияет на основной тезис, т.е. не добавит определенности в случае неоднократного изменения скалярных объектов между соседними точками следования, и уж вовсе никак не влияет на настоящее положение дел в целом.
D>Про 351 нет даже предварительного мнения, когда оно будет тогда и будем говорить undefined или unspecified, пока я вижу двухкратное упоминание unspecified, и однократное undefined, так что с математической точки зрения вероятнее, что опечатка undefined.
Нормативные документы типа стандарта C++ не являются чем-то, что следует трактовать согласно подобным соображениям. Напоминаю, что примеры не являются нормативной частью стандарта и при любых противоречиях примеров и основного текста предпочтение должно отдаваться последнему, независимо от количества примеров. Кроме того, как уже упоминалось, в спорных случаях трактовки стандарта, следует обращаться в comp.std.c++ — официальную группу комитета стандартизации. В последнее время там было несколько обсуждений, касавшихся (не)определенности поведения конструкций вида i = ++i. Ни в одном из известных мне подобных обсуждений между членами комитета не было разногласий относительно трактовки процитированного ранее пункта — все единодушно подтверждали наличие неопределенного поведения при модификации скалярных объектов более одного раза между точками следования. Если вдруг комитет разрешит 351 в пользу unspecified — что, imho, фактически невероятно, иначе, зачем весь сыр-бор с 222? — мы будем считать эти случаи таковыми. До тех же пор все эти случаи, согласно стандарту, приводят к undefined behavior.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Прежде всего давай определимся, о чем идет речь. Я утверждаю, что согласно текущей редакции стандарта модификация скалярных объектов более одного раза между соседними точками следования приводит к неопределенному поведению программы. Если ты споришь с этим, то продолжаем, иначе, пожалуйста, сформулируй свою позицию.
Я утверждаю, что ясности даже с учетом только текущего Стандарта нет. Так как нет даже точной формулировки, что примеры в Стандарте только информативны. Если поискать слово “normative” в Стандарте C++, то первое интересующее нас вхождение будет в 17.3.1.1\2:
Paragraphs labelled ‘‘Note(s):’’ or ‘‘Example(s):’’ are informative, other paragraphs are normative.
Так что в описании библиотеки примеры действительно только информативны, но про core language такое я сказать не могу. В Стандарте С99 ясно сказано Foreword\6:
Annexes D and F form a normative part of this standard; annexes A, B, C, E, G, H, I, J, the bibliography, and the index are for information only. In accordance with Part 3 of the ISO/IEC Directives, this foreword, the introduction, notes, footnotes, and examples are also for information only.
Если бы все примеры в стандарте были информативны, то 17.3.1.1\2 должен был находиться в начале стандарта (как в C99), а не в середине, где речь идет только о стандартной библиотеке, это ясно и 17.3.1.1\1.
D>>об этом еще дискутируют в комитете по стандартизации С++ http://www.dkuug.dk/jtc1/sc22/wg21. Достаточно посмотреть две темы 222 Sequence points and lvalue-returning operators и 351 Sequence point error: unspecified or undefined?. Первая в состоянии drafting, а вторая вообще в состоянии open.
ПК>В 222 подтверждается, что в текущей редакции стандарта — основной нормативный документ для разрешения подобных разногласий — конструкции вида (a += b) += c; приводят к неопределенному поведению. С другой стороны, утверждается, что подобные конструкции могут быть полезны и для этого предлагается изменить существующую спецификацию, причем не в той части, которая вызвала разногласия. Кроме того, уточняются некоторые формулировки относительно случаев типа x = y = 0. Но это уже все совсем другие "пироги".
Я бы сказал не изменить, а точно определить! Так как в текущей версии Стандарта на такие вопросы четких ответов нет.
D>>предлагаемое решение добавление точки следования в операторе присваивания.
ПК>Это не разрешение (несуществующей) неоднозначности, это изменение существующей спецификации, к предмету разговора никакого отношения не имеющее. Когда все операции присваивания, в т.ч. и "простые", будут сопровождаться точками следования, тогда некоторые из приводимых тобой примеров станут примерами не установленного (unspecified behavior), а некоторые и вовсе приобретут точно определенное поведение. Однако это никоим образом не влияет на основной тезис, т.е. не добавит определенности в случае неоднократного изменения скалярных объектов между соседними точками следования, и уж вовсе никак не влияет на настоящее положение дел в целом.
Все зависит от того, где именно будет точка следования, до выполнения присваивания или после. Пока речь идет о добавлении точки следования после выполнения оператора присваивания и до получения результата операции присваивания. Но окончательное решение мы не узнаем как минимум до мая 2003 когда, так как нужно еще как минимум два-три митинга так как тема должна пройти еще два состояния Review и Ready и только потом будет окончательное решение.
D>>Про 351 нет даже предварительного мнения, когда оно будет тогда и будем говорить undefined или unspecified, пока я вижу двухкратное упоминание unspecified, и однократное undefined, так что с математической точки зрения вероятнее, что опечатка undefined.
ПК>Нормативные документы типа стандарта C++ не являются чем-то, что следует трактовать согласно подобным соображениям. Напоминаю, что примеры не являются нормативной частью стандарта и при любых противоречиях примеров и основного текста предпочтение должно отдаваться последнему, независимо от количества примеров. Кроме того, как уже упоминалось, в спорных случаях трактовки стандарта, следует обращаться в comp.std.c++ — официальную группу комитета стандартизации. В последнее время там было несколько обсуждений, касавшихся (не)определенности поведения конструкций вида i = ++i. Ни в одном из известных мне подобных обсуждений между членами комитета не было разногласий относительно трактовки процитированного ранее пункта — все единодушно подтверждали наличие неопределенного поведения при модификации скалярных объектов более одного раза между точками следования. Если вдруг комитет разрешит 351 в пользу unspecified — что, imho, фактически невероятно, иначе, зачем весь сыр-бор с 222? — мы будем считать эти случаи таковыми. До тех же пор все эти случаи, согласно стандарту, приводят к undefined behavior.
i = i = 1; — здесь я думаю, вопросов не возникнет.
i = (i = j + k) + (i = j — k); — здесь поведение будет зависеть от значений.
i = ++i; — здесь вопросы есть
Я считаю, что правильное решение по 351 это сделать поведение не специфицированным, так как иначе при работе с указателями неопределенное поведением может возникать слишком часто в безобидных ситуациях, или сделать точку следования перед выполнением оператора присваивания.
P.S. отвечу на мелкий упрек про неинициализированные данные в моих примерах: считайте, что все переменные объявлены глобальными, а вообще объявления я приводил только для того чтобы тип переменных был точно определен.
Здравствуйте dupamid, Вы писали:
D>Я утверждаю, что ясности даже с учетом только текущего Стандарта нет. Так как нет даже точной формулировки, что примеры в Стандарте только информативны. Если поискать слово “normative” в Стандарте C++, то первое интересующее нас вхождение будет в 17.3.1.1\2: <...>
Стандарт ISO/IEC 14882:1998(E) не является "вещью в себе". Учитывая теорему Геделя ;-), надо искать не в стандарте, накладывающем ограничения на язык C++, а в стандартах, накладывающих ограничения на стандарты ISO/IEC :-) На момент подачи заявки на ISO/IEC 14882:1998(E), если не ошибаюсь, действительными являлись ISO/IEC Directives, Part 3, 1997: Rules for the structure and drafting of International Standards (может, 1989 edition, но в интересующих нас пунктах они не отличаются, а у меня под рукой этого артефакта нет). Итак (1997 Directives, Part 3, внутритекстовые выделения мои):
3.4 normative elements
those elements setting out the provisions to which it is necessary to conform in order to be able to claim compliance with the standard
3.5 informative elements 3.5.1 preliminary elements
those elements that identify the standard, introduce its content and explain its background, its development and its relationship with other standards 3.5.2 supplementary elements
those elements that provide additional information intended to assist the understanding or use of the standard
6.5 Other informative elements 6.5.1 Notes and examples integrated in the text
Notes and examples integrated in the text of a standard shall only be used for giving additional information intended to assist the understanding or use of the standard and shall not contain provisions to which it is necessary to conform in order to be able to claim compliance with the standard.
Для полноты сразу уж и насчет сносок:
6.5.2 Footnotes to the text
Footnotes to the text give additional information; their use shall be kept to a minimum. They shall not contain requirements.
Слово shall, выделенное мною в 6.5.1, согласно ISO/IEC Guide 2:1996, definition 7.1, означает, что данное предложение является требованием, обязательным для выполнения. Таким образом, стандарт ISO/IEC просто не может включать нормативные требования во внутритекстовые примеры и примечания.
D>Если бы все примеры в стандарте были информативны, то 17.3.1.1\2 должен был находиться в начале стандарта (как в C99), а не в середине, где речь идет только о стандартной библиотеке, это ясно и 17.3.1.1\1.
В самом стандарте ISO/IEC 14882:1998(E) дополнительно эти, а также многие другие требования и определения, касающиеся самого стандарта, повторять не обязательно (хотя и можно), они общие для всех стандартов ISO/IEC.
ПК>>В 222 подтверждается, что в текущей редакции стандарта <...> приводят к неопределенному поведению. С другой стороны, утверждается, что подобные конструкции могут быть полезны и для этого предлагается изменить существующую спецификацию, причем не в той части, которая вызвала разногласия. <...>
D>Я бы сказал не изменить, а точно определить! Так как в текущей версии Стандарта на такие вопросы четких ответов нет.
Есть, есть, продолжай медитировать на фразу "Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression." ;-)
D>>>предлагаемое решение добавление точки следования в операторе присваивания.
ПК>>Когда все операции присваивания, в т.ч. и "простые", будут сопровождаться точками следования, тогда некоторые из приводимых тобой примеров станут примерами не установленного (unspecified behavior), а некоторые и вовсе приобретут точно определенное поведение. Однако это никоим образом не влияет на основной тезис, т.е. не добавит определенности в случае неоднократного изменения скалярных объектов между соседними точками следования, и уж вовсе никак не влияет на настоящее положение дел в целом.
D>Все зависит от того, где именно будет точка следования, до выполнения присваивания или после.
Для предмета спора не важно. Главное, что неоднократная модификация скалярных объектов между соседними точками следования приводит к неопределенному поведению. Предлагаемые изменения никак этого не меняют, а только добавляют новые точки следования в некоторых местах, где в настоящий момент их определенно нет.
ПК>>До тех же пор все эти случаи, согласно стандарту, приводят к undefined behavior.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Вы опять прислали очень интересные ссылки, спасибо! Давайте присмотримся к ним повнимательнее.
ПК>3.4 normative elements ПК>those elements setting out the provisions to which it is necessary to conform in order to be able to claim compliance with the standard
ПК>6.5 Other informative elements ПК>6.5.1 Notes and examples integrated in the text ПК>Notes and examples integrated in the text of a standard shall only be used for giving additional information intended to assist the understanding or use of the standard and shall not contain provisions to which it is necessary to conform in order to be able to claim compliance with the standard.
В последнем абзаце только утверждается, что реализация может не поддерживать приведенные примеры и при этом оставаться конформной Стандарту, так как должна следовать общему тексту, а не конкретным примерам. Это очень понятно, так как примеры могут быть не полны и, следовательно, будут не компилироваться в том виде, как они приведены в стандарте и т.д. Но приведенная выше формулировка не говорит, что суть примеров приводимых в Стандарте не имеет значения (и просто является ошибочной) и в них можно писать все что угодно.
ПК>Для полноты сразу уж и насчет сносок:
ПК>6.5.2 Footnotes to the text ПК>Footnotes to the text give additional information; their use shall be kept to a minimum. They shall not contain requirements.
Это вообще рекомендация писателям Стандарта, что они должны стремится к тому, чтобы все требования находились в основном тексте Стандарта, а не где-то еще.
ПК>Слово shall, выделенное мною в 6.5.1, согласно ISO/IEC Guide 2:1996, definition 7.1, означает, что данное предложение является требованием, обязательным для выполнения. Таким образом, стандарт ISO/IEC просто не может включать нормативные требования во внутритекстовые примеры и примечания.
Тут все понятно, значение слова shall в Стандарте тоже проблем не вызывает.
D>>Если бы все примеры в стандарте были информативны, то 17.3.1.1\2 должен был находиться в начале стандарта (как в C99), а не в середине, где речь идет только о стандартной библиотеке, это ясно и 17.3.1.1\1.
ПК>В самом стандарте ISO/IEC 14882:1998(E) дополнительно эти, а также многие другие требования и определения, касающиеся самого стандарта, повторять не обязательно (хотя и можно), они общие для всех стандартов ISO/IEC.
Я согласен, что их можно не повторять, но если они все-таки повторяются, то с какой-то целью, а тем более, если они повторяются не в начале Стандарта, а в его середине и касающейся конкретной его части. Кстати приложения тоже являются информативными, однако в Стандарте С++ явно сказано, что часть приложений нормативна.
ПК>>>В 222 подтверждается, что в текущей редакции стандарта <...> приводят к неопределенному поведению. С другой стороны, утверждается, что подобные конструкции могут быть полезны и для этого предлагается изменить существующую спецификацию, причем не в той части, которая вызвала разногласия. <...>
D>>Я бы сказал не изменить, а точно определить! Так как в текущей версии Стандарта на такие вопросы четких ответов нет.
ПК>Есть, есть, продолжай медитировать на фразу "Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression." ;-)
Продолжаю, только интересующая нас часть находиться дальше: "The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined." и пример далее. А тут уже сложнее, и одной медитацией не обойдешься, надо подождать 351.
D>>>>предлагаемое решение добавление точки следования в операторе присваивания.
ПК>>>Когда все операции присваивания, в т.ч. и "простые", будут сопровождаться точками следования, тогда некоторые из приводимых тобой примеров станут примерами не установленного (unspecified behavior), а некоторые и вовсе приобретут точно определенное поведение. Однако это никоим образом не влияет на основной тезис, т.е. не добавит определенности в случае неоднократного изменения скалярных объектов между соседними точками следования, и уж вовсе никак не влияет на настоящее положение дел в целом.
D>>Все зависит от того, где именно будет точка следования, до выполнения присваивания или после.
ПК>Для предмета спора не важно. Главное, что неоднократная модификация скалярных объектов между соседними точками следования приводит к неопределенному поведению. Предлагаемые изменения никак этого не меняют, а только добавляют новые точки следования в некоторых местах, где в настоящий момент их определенно нет.
Пока не ясно к чему она приводит, есть два мнения либо к не специфицированному, либо к не определенному, надо ждать 351.
ПК>>>До тех же пор все эти случаи, согласно стандарту, приводят к undefined behavior.
Здравствуйте dupamid, Вы писали:
ПК>>Notes and examples integrated in the text of a standard shall only be used for giving additional information intended to assist the understanding or use of the standard and shall not contain provisions to which it is necessary to conform in order to be able to claim compliance with the standard.
D>В последнем абзаце только утверждается, что реализация может не поддерживать приведенные примеры и при этом оставаться конформной Стандарту, так как должна следовать общему тексту, а не конкретным примерам.
1) Нормативные положения (provision) стандарта определяют требования, рекомендации и т.п. к реализации.
2) В последнем абзаце утверждается, что ни один стандарт ISO/IEC не может содержать нормативные положения (provisions) во внутритекстовых примерах и примечаниях.
3) В применении к предмету разговора это означает, что если в нормативной части сказано, что модификация скалярного объекта между двумя соседними точками следования приводит к неопределенному поведению, а в примере подобная ситуация помечена комментарием `unspecified', то поведение undefined, т.к. никакая реализация не обязана следовать комментариям в примере.
D>приведенная выше формулировка не говорит, что суть примеров приводимых в Стандарте не имеет значения
Приведенная формулировка говорит, что значение примеров заключается только в предоставлении дополнительной информации, предназначенной для облегчения понимания основной (нормативной) части. Если в примере содержится ошибка, это означает, что пример со своей задачей не справился.
D>(и просто является ошибочной) и в них можно писать все что угодно.
Этого я и не утверждал, поосторожнее с модификацией позиции собеседника.
ПК>>Footnotes to the text give additional information; their use shall be kept to a minimum. They shall not contain requirements.
D>Это вообще рекомендация писателям Стандарта, что они должны стремится к тому, чтобы все требования находились в основном тексте Стандарта, а не где-то еще.
Это не рекомендации, а требования (shall), которые заключаются в том, что
1) Использование сносок должно быть минимизировано.
2) Сноски не могут содержать требования. В данном случае requirement это термин. Нормативные положения (provision) стандартов делятся на: statement (3.8.1), instruction (3.8.2), recommendation (3.8.3) и, наконец, requirement (3.8.4). Таким образом, в отличие от внутритекстовых примеров и примечаний, сноски могут содержать нормативные положения, кроме требований.
ПК>>Таким образом, стандарт ISO/IEC просто не может включать нормативные требования во внутритекстовые примеры и примечания.
D>Тут все понятно, значение слова shall в Стандарте тоже проблем не вызывает.
Если это понятно, то должно быть также понятно, что аргументация цитатой из внутритекстового примера при наличии нормативного положения является некорректной.
D>Я согласен, что их можно не повторять, но если они все-таки повторяются, то с какой-то целью, а тем более, если они повторяются не в начале Стандарта, а в его середине и касающейся конкретной его части.
Считай это стилистическим различием. "Основную" и "библиотечную" части стандарта готовили разные люди.
D>Кстати приложения тоже являются информативными, однако в Стандарте С++ явно сказано, что часть приложений нормативна.
Есть существенная разница. Приложения, в отличие от внутритекстовых примеров и примечаний могут быть информативными или нормативными, причем, согласно п. 6.3.8 и 6.4.1 в стандарте должно быть четко указано, какие из них являются какими.
D>>>в текущей версии Стандарта на такие вопросы четких ответов нет.
D>интересующая нас часть находиться дальше: "The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined."
Если рассмотреть только нормативную часть абзаца 5/4 без затуманивающего примера, то относительно множественной модификации скалярных объектов между соседними точками следования все кристально ясно:
<... сначала про не установленный порядок вычисления ...> Между предыдущей и следующей точками следования значение скалярного объекта должен модифицироваться не более одного раза при вычислении выражения <... еще большие ограничения ...> Требования данного абзаца должны выполняться для всех возможных порядков вычисления подвыражений полного выражения, иначе поведение не определено.
Таким образом, если хотя бы для одного возможного порядка вычисления подвыражений допускается неоднократное изменение значения скалярного объекта между соседними точками следования, поведение не определено. Что здесь не ясно?!
D>Пока не ясно к чему она приводит, есть два мнения либо к не специфицированному, либо к не определенному,
Первое мнение пока что ничем, кроме ненормативного примера не подтверждается. Второе подкрепляется нормативной частью стандарта и высказываниями людей, которые составляли стандарт. Более того, под unspecified одновременная модификация скалярных объектов никак не подходит, т.к. во многих случаях невозможно перечислить возможный диапазон значений.
D>надо ждать 351.
Вот же упрямец... :-) Ну, жди. Если бы не ленился, поискал бы архивы аналогичных обсуждений в comp.std.c++ и comp.lang.c++.moderated, где принимали участие те же члены комитета, которые будут голосовать по 351. Ладно, помогу. Вот соответствующие реплики пары давних членов комитета, один из которых, помимо прочего, является разработчиком компилятора:
Francis Glassborow: >Now: the effect of ++i + ++i is *unspecified*. This means, that there is some limited number of possibilities (3?) and exactly one of them can happen. The undefined concerns the access and modification rules wich have to be met with different orderings (can they be violated here?).
Clause 5 para 4, sentence 2
Between the previous and next sequence point a scalar object SHALL (my emphasis) have its stored value modified at most once by the evaluation of an expression.
That 'shall' is mandatory and breaching it results in behaviour outside the scope of the Standard, i.e. undefined behaviour.
The example is WRONG. Both uses of unspecified should be undefined.
Steve Clamage:
multiple modifications between sequence points
The infamous cases "i = i++" and "a[i] = i++" can be detected by the compiler. Perhaps some compilers do detect them. But consider this entire compilation unit:
extern int i;
int foo(int* p) { return ++i + ++*p; }
The code is OK unless p points to i, in which case the results are not defined. If we require detection of multiple modification, the compiler would have to generate runtime code to check for aliasing (as this case is called, since different things refer to the same object), which could be very expensive. User code would also have to be prepared to deal with whatever the error reporting mechanism is -- probably an exception.
So why "undefined" instead of defining a complete ordering on expressions? It allows compilers the freedom to generate efficient code. Given a complicated expression with no sequence points, the compiler is allowed to assume that the order of side effects doesn't matter, and so can do things in the way that uses the least space and time. In cases where the order of side effects does matter, you tell the compiler by inserting a sequence point -- like a semicolon or a comma. So instead of "a[i]=i++", you can write "(a[i]=i, ++i)" if that is what you meant. In other words, compilers can generate the most efficient code possible, and only those expressions where the order of side effects matters need experience a slowdown.
Finally, why "undefined" instead of "unspecified" or "implementation defined"? The latter two cases would require defining all the possible outcomes, which isn't practical to do in the general case. (It might not even be possible.)
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
D>>приведенная выше формулировка не говорит, что суть примеров приводимых в Стандарте не имеет значения
ПК>Приведенная формулировка говорит, что значение примеров заключается только в предоставлении дополнительной информации, предназначенной для облегчения понимания основной (нормативной) части. Если в примере содержится ошибка, это означает, что пример со своей задачей не справился.
D>>(и просто является ошибочной) и в них можно писать все что угодно.
ПК>Этого я и не утверждал, поосторожнее с модификацией позиции собеседника.
Странно, что Вы это приняли за свою, но модифицированную позицию – это мои собственные мысли.
Что касается остального, то спор себя исчерпал – решение по 351 действительно, скорее всего будет в пользу undefined, хотя это слишком сурово для С++. Для С это может сгодиться так как там нет ссылок и шаблонов, которые затуманивают текст и делают незаметным двукратную модификацию одной переменой между точками следования. Более того, на подавляющем большинстве систем ничего страшного от одновременной модификации одной и той же переменной не произойдет и формулировка unspecified более подходит, так как переменная просто получит одно из значений. Выигрыш от разрешения реализации таких оптимизаций, при которой она может не следить за одновременной модификацией переменной, крайне сомнителен. Стандарт мог бы потребовать генерацию кода, гарантирующую работу программы без сбоев в таких случаях, это не вызвало бы больших накладных расходов.
Здравствуйте dupamid, Вы писали:
ПК>>Этого я и не утверждал, поосторожнее с модификацией позиции собеседника. D>Странно, что Вы это приняли за свою, но модифицированную позицию – это мои собственные мысли.
Извини, был не в духе, чуть было не начал сорить фразами из серии "Ошибка аргументации #..."
D>Что касается остального, то спор себя исчерпал – решение по 351 действительно, скорее всего будет в пользу undefined, хотя это слишком сурово для С++. <...> на подавляющем большинстве систем ничего страшного от одновременной модификации одной и той же переменной не произойдет и формулировка unspecified более подходит, так как переменная просто получит одно из значений.
Это в случае, если модификация является атомарной и/или вычисления выполняются последовательно. А если, скажем в "++i + ++i + ++i" каждая операция ++ выполняется процессором в два-три шага, и обе операции при этом могут выполняться действительно одновременно? "Страшного" действительно, скорее всего ничего не будет, но и определить варианты принимаемых значений в общем случае тоже не представляется возможным.
D>Выигрыш от разрешения реализации таких оптимизаций, при которой она может не следить за одновременной модификацией переменной, крайне сомнителен. Стандарт мог бы потребовать генерацию кода, гарантирующую работу программы без сбоев в таких случаях, это не вызвало бы больших накладных расходов.
В применении к приведенному примеру это может означать запрет использования возможности процессора выполнять вычисления параллельно во всех выражениях вида "++*p + ++*q".
... << J 1.0 alpha 4 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
ПК>>>Этого я и не утверждал, поосторожнее с модификацией позиции собеседника. D>>Странно, что Вы это приняли за свою, но модифицированную позицию – это мои собственные мысли. ПК>Извини, был не в духе, чуть было не начал сорить фразами из серии "Ошибка аргументации #..."
Бывает
ПК>Это в случае, если модификация является атомарной и/или вычисления выполняются последовательно. А если, скажем в "++i + ++i + ++i" каждая операция ++ выполняется процессором в два-три шага, и обе операции при этом могут выполняться действительно одновременно? "Страшного" действительно, скорее всего ничего не будет, но и определить варианты принимаемых значений в общем случае тоже не представляется возможным.
Если проблема только в значении, то обычно это unspecified, что и было бы хорошо в этом случае.
D>>Выигрыш от разрешения реализации таких оптимизаций, при которой она может не следить за одновременной модификацией переменной, крайне сомнителен. Стандарт мог бы потребовать генерацию кода, гарантирующую работу программы без сбоев в таких случаях, это не вызвало бы больших накладных расходов. ПК>В применении к приведенному примеру это может означать запрет использования возможности процессора выполнять вычисления параллельно во всех выражениях вида "++*p + ++*q".
Да, но, специальная поддержка потребуется далеко не на всех системах, а вот неопределенное поведение возникает на всех системах. С++ имеет очень сложную семантику (часто скрытую) и ее не всегда хорошо видно по исходному тексту, так что сделать его немного более безопасным только хорошо, если при этом накладные расходы либо вообще отсутствуют, либо не очень большие.
Вы видимо удалили это свое сообщение, но я на него успел ответить
ПК>Unspecified обычно это когда варианты могут быть определены, но какой из них будет выбран неизвестно.
Во многом схожая ситуация с порядком вычисления аргументов при вызове функции, какой будет порядок зависит от слишком многих факторов и в общем случае не известен, так как даже может меняться от debug к release версии сборки. Поведение в этом случае не определено.
ПК>>>это может означать запрет использования возможности процессора выполнять вычисления параллельно во всех выражениях вида "++*p + ++*q".
D>>Да, но, специальная поддержка потребуется далеко не на всех системах,
ПК>Например, в случае "++*p + ++*q" — на всех мне известных. Например, нельзя сгенерировать последовательность такую:
ПК>
ПК>нарастить *p
ПК>нарастить *q
ПК>сложить *p и *q
ПК>
Может быть я не совсем понимаю, что Вы имеете в виду, это не то?
inc [p]
inc [q]
mov eax, [p]
add eax, [q]
D>>а вот неопределенное поведение возникает на всех системах. С++ имеет очень сложную семантику (часто скрытую) и ее не всегда хорошо видно по исходному тексту, так что сделать его немного более безопасным только хорошо, если при этом накладные расходы либо вообще отсутствуют, либо не очень большие.
ПК>Ключевое слово "если". Кроме того, если на любой из систем поведение не определено, в стандарте все равно будет undefined behavior.
Это странное утверждение. Всегда существет (или может существовать) система где самые банальные вещи могут приводить к не определенному поведению, что же тогда должны страдать все остальные системы, на которых таких проблем нет?
Здравствуйте dupamid, Вы писали:
ПК>>если, скажем в "++i + ++i + ++i" каждая операция ++ выполняется процессором в два-три шага, и обе операции при этом могут выполняться действительно одновременно? "Страшного" действительно, скорее всего ничего не будет, но и определить варианты принимаемых значений в общем случае тоже не представляется возможным.
D>Если проблема только в значении, то обычно это unspecified, что и было бы хорошо в этом случае.
Unspecified обычно это когда варианты могут быть определены, но какой из них будет выбран неизвестно.
D>специальная поддержка потребуется далеко не на всех системах, а вот неопределенное поведение возникает на всех системах. С++ имеет очень сложную семантику (часто скрытую) и ее не всегда хорошо видно по исходному тексту, так что сделать его немного более безопасным только хорошо, если при этом накладные расходы либо вообще отсутствуют, либо не очень большие.
Ключевое слово "если". Кроме того, если на любой из систем поведение не определено, в стандарте все равно будет undefined behavior.
... << J 1.0 alpha 4 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте dupamid, Вы писали:
D>Вы видимо удалили это свое сообщение, но я на него успел ответить
Да, утром я не вполне понял, что я хотел сказать этим высказыванием:
ПК>>Например, в случае "++*p + ++*q" — на всех мне известных. Например, нельзя сгенерировать последовательность такую: <...>
Поэтому удалил эти строки и снова послал это же сообщение.
ПК>>Unspecified обычно это когда варианты могут быть определены, но какой из них будет выбран неизвестно.
D>Во многом схожая ситуация с порядком вычисления аргументов при вызове функции, какой будет порядок зависит от слишком многих факторов и в общем случае не известен, так как даже может меняться от debug к release версии сборки. Поведение в этом случае не определено.
Нет, поведение в этом случае не установлено, даже точнее не установлен порядок вычисления аргументов, т.к. в принципе можно перечислить все возможные варианты, но нельзя сказать который из них будет выбран.
D>Может быть я не совсем понимаю, что Вы имеете в виду, это не то?
Как я уже сказал, я и сам не понял, что я имел в виду
ПК>>Ключевое слово "если". Кроме того, если на любой из систем поведение не определено, в стандарте все равно будет undefined behavior.
D>Это странное утверждение. Всегда существет (или может существовать) система где самые банальные вещи могут приводить к не определенному поведению,
Например?
D>что же тогда должны страдать все остальные системы, на которых таких проблем нет?
Нет, любая реализация вольна "определить" любое неопределенное поведение.
... << J 1.0 alpha 4 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
ПК>>>Unspecified обычно это когда варианты могут быть определены, но какой из них будет выбран неизвестно.
D>>Во многом схожая ситуация с порядком вычисления аргументов при вызове функции, какой будет порядок зависит от слишком многих факторов и в общем случае не известен, так как даже может меняться от debug к release версии сборки. Поведение в этом случае не определено.
ПК>Нет, поведение в этом случае не установлено, даже точнее не установлен порядок вычисления аргументов, т.к. в принципе можно перечислить все возможные варианты, но нельзя сказать который из них будет выбран.
Поведение в этом случае unspecified, термин «не установлено» мне кажется не совсем удачным. Число последовательностей вычисления аргументов у функции с n параметрами будет n!, что для 13 параметров больше чем может принимать 32-х разрядное число. Так как в компьютерах арифметика с ограниченной точностью, то все значение переменной тоже можно теоретически перечислить и переменная, скорее всего, будет иметь одно из этих значений.
ПК>>>Ключевое слово "если". Кроме того, если на любой из систем поведение не определено, в стандарте все равно будет undefined behavior.
D>>Это странное утверждение. Всегда существует (или может существовать) система где самые банальные вещи могут приводить к не определенному поведению,
ПК>Например?
Гипотетический пример. Существует система, на которой значение ячейки памяти может быть записано не полностью, а частично при возникновении сигнала (прерывания), если не взвести специальный запрет на прерывание при записи. Когда сигнал будет обработан правильное значение ячейка все равно не получит. Выходит, что Стандарт должен сказать, что запись в любую ячейку памяти имеет не определенное поведение.
D>>что же тогда должны страдать все остальные системы, на которых таких проблем нет?
ПК>Нет, любая реализация вольна "определить" любое неопределенное поведение.
Может, но программа от этого все равно останется ill-formed, так как полагается на неопределенное поведение.
Здравствуйте dupamid, Вы писали:
ПК>>Нет, поведение в этом случае не установлено, даже точнее не установлен порядок вычисления аргументов, т.к. в принципе можно перечислить все возможные варианты, но нельзя сказать который из них будет выбран.
D>Поведение в этом случае unspecified, термин «не установлено» мне кажется не совсем удачным.
Whatever, но unspecified переводится именно так.
D>Число последовательностей вычисления аргументов у функции с n параметрами будет n!, что для 13 параметров больше чем может принимать 32-х разрядное число.
Это не важно. Главное, что все они потенциально могут быть перечислены.
D>Так как в компьютерах арифметика с ограниченной точностью, то все значение переменной тоже можно теоретически перечислить и переменная, скорее всего, будет иметь одно из этих значений.
Не вполне. Например, значащие биты скалярного типа могут занимать меньше чем sizeof(тип) * CHAR_BIT. При одновременной модификации значения результат может оказаться не представимым данной битовой маской со всеми вытекающими вплоть до core dump. Например, на Cray не все биты некоторых скалярных типов являются значащими.
D>>>Это странное утверждение. Всегда существует (или может существовать) система где самые банальные вещи могут приводить к не определенному поведению,
ПК>>Например?
D>Гипотетический пример. Существует система, на которой значение ячейки памяти может быть записано не полностью, а частично при возникновении сигнала (прерывания), если не взвести специальный запрет на прерывание при записи. Когда сигнал будет обработан правильное значение ячейка все равно не получит. Выходит, что Стандарт должен сказать, что запись в любую ячейку памяти имеет не определенное поведение.
Прерывания, так же как и (почти?) любая асинхронность, являются понятиями за пределами стандарта. Поэтому, фактически, любое асинхронное взаимодействие само по себе автоматом приводит к undefined behavior.
D>>>что же тогда должны страдать все остальные системы, на которых таких проблем нет? ПК>>Нет, любая реализация вольна "определить" любое неопределенное поведение. D>Может, но программа от этого все равно останется ill-formed, так как полагается на неопределенное поведение.
Нет ill-formed означает, что в программе есть синтаксические ошибки и/или диагностируемые семантические и/или нарушено One Definition Rule. Выполнение well-formed программы может приводить к undefined behavior.
... << J 1.0 alpha 4 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
D>>Поведение в этом случае unspecified, термин «не установлено» мне кажется не совсем удачным.
ПК>Whatever, но unspecified переводится именно так.
На мой взгляд, англоязычный термин «не специфицировано» более точно отражает смысл, но это дело вкуса и значения не имеет.
D>>Число последовательностей вычисления аргументов у функции с n параметрами будет n!, что для 13 параметров больше чем может принимать 32-х разрядное число.
ПК>Это не важно. Главное, что все они потенциально могут быть перечислены.
Так и значения любого числа с ограниченным числом бит тоже могут быть перечислены, даже если не все из них могут получаться в результате арифметических операций. Так что большой разницы я не вижу.
D>>Так как в компьютерах арифметика с ограниченной точностью, то все значение переменной тоже можно теоретически перечислить и переменная, скорее всего, будет иметь одно из этих значений.
ПК>Не вполне. Например, значащие биты скалярного типа могут занимать меньше чем sizeof(тип) * CHAR_BIT. При одновременной модификации значения результат может оказаться не представимым данной битовой маской со всеми вытекающими вплоть до core dump. Например, на Cray не все биты некоторых скалярных типов являются значащими.
Формула sizeof(тип) * CHAR_BIT вообще в корне не верна – она не позволяет вычислить число бит в типе. Пример, может быть система, на которой sizeof(type) для всех встроенных типов и «обычных указателей» равен 1, но число бит и диапазоны значений для типов разные.
То, что некоторые комбинации бит в типе могут быть недопустимы, и приводить к печальным последствиям не означает, что их (значения) нельзя все перечислить.
ПК>Прерывания, так же как и (почти?) любая асинхронность, являются понятиями за пределами стандарта. Поэтому, фактически, любое асинхронное взаимодействие само по себе автоматом приводит к undefined behavior.
Сигналы не являются понятиями за пределами Стандарта, а они асинхронны.
Здравствуйте Павел Кузнецов, Вы писали:
ПК>>>Нет, любая реализация вольна "определить" любое неопределенное поведение. D>>Может, но программа от этого все равно останется ill-formed, так как полагается на неопределенное поведение.
ПК>Нет ill-formed означает, что в программе есть синтаксические ошибки и/или диагностируемые семантические и/или нарушено One Definition Rule. Выполнение well-formed программы может приводить к undefined behavior.
Вот определения undefined и unspecified из Стандарта (выдрано из FD так как нет Стандарта под рукой, но думаю, что отличий нет). Так что программа unspecified является well-formed, а вот undefined – это ошибочная программа, для которой Стандарт ничего не гарантирует. Так что даже если реализация все уточнит программа все равно останется невалидной с точки зрения Стандарта.
1.3.12 — undefined behavior [defns.undefined]
behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements. Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior. [Note: permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. ]
1.3.13 — unspecified behavior [defns.unspecified]
behavior, for a well-formed program construct and correct data, that depends on the implementation. The implementation is not required to document which behavior occurs. [Note: usually, the range of possible behaviors is delineated by this International Standard. ]
Здравствуйте dupamid, Вы писали:
D>>>Число последовательностей вычисления аргументов у функции с n параметрами будет n!, что для 13 параметров больше чем может принимать 32-х разрядное число.
ПК>>Это не важно. Главное, что все они потенциально могут быть перечислены.
D>Так и значения любого числа с ограниченным числом бит тоже могут быть перечислены, даже если не все из них могут получаться в результате арифметических операций. Так что большой разницы я не вижу.
Могут быть перечислены все потенциальные комбинации битов. Однако, если некоторые из этих комбинаций недопустимы, то варианты дальнейшего поведения программы в общем случае перечислены быть не могут.
D>>>Так как в компьютерах арифметика с ограниченной точностью, то все значение переменной тоже можно теоретически перечислить и переменная, скорее всего, будет иметь одно из этих значений.
ПК>>Не вполне. Например, значащие биты скалярного типа могут занимать меньше чем sizeof(тип) * CHAR_BIT. При одновременной модификации значения результат может оказаться не представимым данной битовой маской со всеми вытекающими вплоть до core dump. Например, на Cray не все биты некоторых скалярных типов являются значащими.
D>Формула sizeof(тип) * CHAR_BIT вообще в корне не верна – она не позволяет вычислить число бит в типе.
Формула sizeof(тип) * CHAR_BIT позволяет вычислить число бит в объектном представлении типа (object representation), т.е. число бит, которое необходимо для хранения значения данного типа. Возможно, что не все из этих бит будут значащими (value representation).
3.9 Types 4 The object representation of an object of type T is the sequence of N unsigned char objects taken up
by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T. For POD types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementationdefined set of values.
D>Пример, может быть система, на которой sizeof(type) для всех встроенных типов и «обычных указателей» равен 1, но число бит и диапазоны значений для типов разные.
Нет, такая система невозможна.
3.9.1 Fundamental types 1 For character types, all bits of the object representation participate in the value representation. For unsigned character types, all possible bit patterns of the value representation represent numbers. These requirements do not hold for other types.
Кроме того,
2 “signed char”, “short int”, “int”, and “long int.” In this list, each type provides at least as much storage as those preceding it in the list.
Таким образом, т.к. все биты представления char являются значащими, и short представляет не меньший диапазон значений, чем char, а также sizeof(short) == 1, все биты short также являются значащими. То же по индукции для остальных целочисленных типов.
D>То, что некоторые комбинации бит в типе могут быть недопустимы, и приводить к печальным последствиям не означает, что их (значения) нельзя все перечислить.
Но нельзя перечислить варианты поведения программы при образовании недопустимых битовых комбинаций. Это и означает undefined behavior.
ПК>>Прерывания, так же как и (почти?) любая асинхронность, являются понятиями за пределами стандарта. Поэтому, фактически, любое асинхронное взаимодействие само по себе автоматом приводит к undefined behavior.
D>Сигналы не являются понятиями за пределами Стандарта, а они асинхронны.
Именно поэтому я и написал "почти". Но стандарт, фактически, не определяет семантику сигналов, а просто констатирует их наличие. Однако, если в твоем примере заменить прерывание на сигнал, то:
[i]9 When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects with type other than volatile sig_atomic_t are unspecified, and the value of any object not of volatile sig_atomic_t that is modified by the handler becomes undefined.[/b]
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен