Re[47]: Зачем плюс?
От: B0FEE664  
Дата: 08.01.19 09:54
Оценка:
Здравствуйте, σ, Вы писали:

BFE>>

BFE>>The intent is that the memory model of C++ is compatible with that of ISO/IEC 9899 Programming Language C.

σ>intent intent-ом, но если до C++17 ещё можно было разными демагогическими приёмами высосать из пальца то, что получится указатель на первый байт, в C++17 это уже невозможно.

Я не знаю, почему вам это кажется невозможным, так как в последнем драфте есть те же утверждения.
Например, можно сделать так:
  int n = 111;
  void* p = &n;
  char* pA = static_cast<char*>(p);


Мы гарантированно получим указатель на первый байт инта.

Из n4778 : 6.7.2/3 :

A value of a pointer type that is a pointer to or past the end of an object represents the address of the first
byte in memory (6.6.1) occupied by the object or the first byte in memory after the end of the storage
occupied by the object, respectively.


n4778 : 7.6.1.9/12:

A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is
an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original
pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement
of T, then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an
object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible (6.7.2)
with a, the result is a pointer to b.
Otherwise, the pointer value is unchanged by the conversion.


Указатель на первый байт мы получили. Разыменование указателя на первый байт даёт implementation defined значение (лень искать точную ссылку).
Когда здесь
Автор: σ
Дата: 29.11.18
вы ссылаетесь на Lvalue-to-rvalue conversion, то вы ошибочно полагаете, что в c будет записываться значение из i. Это ниоткуда не следует. На самом деле указатель reinterpret_cast<char*>(&i) ссылается не на объект i, а на другой объект: объект типа char. Значение этого объекта типа char в C++17 — implementation defined, а в С++20 оно тоже будет implementation defined, но так как будет зафиксировано битовое представление int, то можно будет даже точно знать значение char.
И каждый день — без права на ошибку...
Re[48]: Зачем плюс?
От: σ  
Дата: 08.01.19 12:02
Оценка:
BFE>>>

BFE>>>The intent is that the memory model of C++ is compatible with that of ISO/IEC 9899 Programming Language C.

σ>>intent intent-ом, но если до C++17 ещё можно было разными демагогическими приёмами высосать из пальца то, что получится указатель на первый байт, в C++17 это уже невозможно.

BFE>Я не знаю, почему вам это кажется невозможным, так как в последнем драфте есть те же утверждения.

BFE>Например, можно сделать так:
BFE>
BFE>  int n = 111;
BFE>  void* p = &n;
BFE>  char* pA = static_cast<char*>(p);
BFE>


BFE>Мы гарантированно получим указатель на первый байт инта.


Не получим.

BFE>Из n4778 : 6.7.2/3 :

BFE>

BFE>A value of a pointer type that is a pointer to or past the end of an object represents the address of the first
BFE>byte in memory (6.6.1) occupied by the object or the first byte in memory after the end of the storage
BFE>occupied by the object, respectively.


BFE>n4778 : 7.6.1.9/12:


BFE>

BFE>A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is
BFE>an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original
BFE>pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement
BFE>of T, then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an
BFE>object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible (6.7.2)
BFE>with a, the result is a pointer to b.
Otherwise, the pointer value is unchanged by the conversion.


BFE>Указатель на первый байт мы получили.


char и int не pointer-interconvertible, да и нет там объекта типа char.

BFE>Когда здесь
Автор: σ
Дата: 29.11.18
вы ссылаетесь на Lvalue-to-rvalue conversion, то вы ошибочно полагаете, что в c будет записываться значение из i.


Да, я уже написал в http://rsdn.org/forum/cpp/7342042.1
Автор: σ
Дата: 07.01.19
, что там UB.

BFE> Это ниоткуда не следует. На самом деле указатель reinterpret_cast<char*>(&i) ссылается не на объект i, а на другой объект: объект типа char.


Цитата из стандарта выше явно говорит что значение этого указателя не меняется. Значение как было "указатель на i", таким и остаётся.
Re[49]: Зачем плюс?
От: B0FEE664  
Дата: 08.01.19 13:08
Оценка:
Здравствуйте, σ, Вы писали:

σ>char и int не pointer-interconvertible, да и нет там объекта типа char.

А как тогда трактовать выделенное?:

Two objects a and b are pointer-interconvertible if:
(4.1) — they are the same object, or
(4.2) — one is a union object and the other is a non-static data member of that object (10.4), or
(4.3) — one is a standard-layout class object and the other is the first non-static data member of that object,
or, if the object has no non-static data members, any base class subobject of that object (10.3), or
(4.4) — there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-
interconvertible.

char и int — standard-layout classes, они не имеют статических членов и не имеют подобъектов.

BFE>>Когда здесь
Автор: σ
Дата: 29.11.18
вы ссылаетесь на Lvalue-to-rvalue conversion, то вы ошибочно полагаете, что в c будет записываться значение из i.

σ>Да, я уже написал в http://rsdn.org/forum/cpp/7342042.1
Автор: σ
Дата: 07.01.19
, что там UB.


reinterpret_cast<char*>(&i);
и
reinterpret_cast<std::uint8_t &>(x)

— это разные касты. Второй, быть может, UB.

BFE>> Это ниоткуда не следует. На самом деле указатель reinterpret_cast<char*>(&i) ссылается не на объект i, а на другой объект: объект типа char.

σ>Цитата из стандарта выше явно говорит что значение этого указателя не меняется. Значение как было "указатель на i", таким и остаётся.
Значение указателя — адрес. Адрес не меняется.
И каждый день — без права на ошибку...
Re[50]: Зачем плюс?
От: σ  
Дата: 08.01.19 13:15
Оценка:
σ>>char и int не pointer-interconvertible, да и нет там объекта типа char.
BFE>А как тогда трактовать выделенное?
Так, как написано.

BFE>char и int — standard-layout classes



BFE>>>Когда здесь
Автор: σ
Дата: 29.11.18
вы ссылаетесь на Lvalue-to-rvalue conversion, то вы ошибочно полагаете, что в c будет записываться значение из i.

σ>>Да, я уже написал в http://rsdn.org/forum/cpp/7342042.1
Автор: σ
Дата: 07.01.19
, что там UB.

BFE>reinterpret_cast<char*>(&i);
BFE>и
BFE>reinterpret_cast<std::uint8_t &>(x)

BFE>- это разные касты. Второй, быть может, UB.


http://rsdn.org/forum/cpp/7342042.1
Автор: σ
Дата: 07.01.19
: "Эти рассуждения справедливы и для unsigned int prvalue, которое получилось преобразованием lvalue, ссылавшимся на signed int с отрицательным значением. И для попытки читать из переменной с типом int через char glvalue значения, не влезающие в char. "

BFE>>> Это ниоткуда не следует. На самом деле указатель reinterpret_cast<char*>(&i) ссылается не на объект i, а на другой объект: объект типа char.

σ>>Цитата из стандарта выше явно говорит что значение этого указателя не меняется. Значение как было "указатель на i", таким и остаётся.
BFE>Значение указателя — адрес.
https://timsong-cpp.github.io/cppwp/n4659/basic.compound#3 :
Every value of pointer type is one of the following:
— a pointer to an object or function (the pointer is said to point to the object or function), or
— a pointer past the end of an object ([expr.add]), or
— the null pointer value ([conv.ptr]) for that type, or
— an invalid pointer value.
Re[51]: Зачем плюс?
От: B0FEE664  
Дата: 08.01.19 14:24
Оценка:
Здравствуйте, σ, Вы писали:

BFE>>char и int — standard-layout classes

σ>
Ну хорошо, они — standard-layout types.
Уверен, что и для них найдётся подходящий пункт.
И каждый день — без права на ошибку...
Re[52]: Зачем плюс?
От: σ  
Дата: 08.01.19 14:26
Оценка:
BFE>Уверен, что и для них найдётся подходящий пункт.
Главное — искренне верить.
Re[51]: Зачем плюс?
От: B0FEE664  
Дата: 08.01.19 14:59
Оценка:
Здравствуйте, σ, Вы писали:

BFE>>Значение указателя — адрес.

σ>https://timsong-cpp.github.io/cppwp/n4659/basic.compound#3 :
σ>Every value of pointer type is one of the following:
σ> — a pointer to an object or function (the pointer is said to point to the object or function), or
σ> — a pointer past the end of an object ([expr.add]), or
σ> — the null pointer value ([conv.ptr]) for that type, or
σ> — an invalid pointer value.

И что? Да, указатель указывает на объект, функцию, конец объект или имеет нулевое значение или невалидное значение.

Из 7.6.2.1/3: речь про операцию взятия адреса:

if the type of the expression is T, the result has type “pointer to T” and is a prvalue that is the address of
the designated object
(6.6.1) or a pointer to the designated function.

И каждый день — без права на ошибку...
Re[53]: Зачем плюс?
От: B0FEE664  
Дата: 08.01.19 16:22
Оценка:
Здравствуйте, σ, Вы писали:

BFE>>Уверен, что и для них найдётся подходящий пункт.

σ>Главное — искренне верить.
Раз есть строчка:

An object pointer can be explicitly converted to an object pointer of a different type.

то пункт должен найтись.
И каждый день — без права на ошибку...
Re[45]: Зачем плюс?
От: N. I.  
Дата: 08.01.19 16:58
Оценка:
σ:

σ>В твоём примере кода тоже неопределённое поведение, причём об этом в стандарте сказано явно.


Вот только таким "явным" образом стандарт трактовать не принято.

σ>[conv.lval]/1:

σ>An lvalue (3.10) of a non-function, non-array type T can be converted to an rvalue. If T is an incomplete
σ>type, a program that necessitates this conversion is ill-formed. If the object to which the lvalue refers is not
σ>an object of type T
and is not an object of a type derived from T, or if the object is uninitialized, a program
σ>that necessitates this conversion has undefined behavior.


Здесь ещё до кучи можно приколупаться к отсутствию определения "uninitialized object".

#include <iostream>

int main()
{
    int x;
    x = 0;
    std::cout << +x;
}

Эти стандарты, вроде бы, нигде не говорят, что просле присваивания x становится initialized, так что на lvalue-to-rvalue conversion в +x вполне можно получить undefined behavior, если трактовать uninitialized как буквальное отсутствие у объекта x инициализации. Эта проблема упомянута в DR 240.

В общем, если увлекаться буквальным прочтением правил и задаться целью писать идеально well-defined программы для сферического компилятора в вакууме, это будет довольно суровым и практически неоправданным бременем на пути к реализации полезного функционала.

σ>lvalue типа uint8_t ссылается на объект типа int8_t → UB при lvalue-to-rvalue conversion


σ>В C++98/03 и 11 UB всегда.


На практике — скорее всего, никогда. Для чего тогда вообще надо было упоминать про доступ через lvalue of "a type that is the signed or unsigned type corresponding to the dynamic type of the object" в [basic.lval]?

σ>Я тыкал в последнее правило утверждая, что результатом будет то-то и то-то и это определённое поведение. Но надо обратить внимание на последнее предложение в [conv.lval]/1 и на [expr]/4:

σ>If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

σ>L-to-R, применённый к reinterpret_cast<std::uint8_t &>(x) имеет тип uint8_t, но значение, которое является результатом этого выражения — -1 (the value contained in the object indicated by the glvalue) — is not in the range of representable values for its type. Следовательно, the behavior is undefined.


Сомневаюсь, что такая трактовка реально подразумевается (повторюсь: практическое значение имеет только подразумеваемая интерпретация правил, а не то, что получается при их буквальном прочтении).

σ>Эти рассуждения справедливы и для unsigned int prvalue, которое получилось преобразованием lvalue, ссылавшимся на signed int с отрицательным значением. И для попытки читать из переменной с типом int через char glvalue значения, не влезающие в char.


Эта трактовка стопудово расходится с замыслом авторов правил и с практической точки зрения бесполезна.
Re[46]: Зачем плюс?
От: σ  
Дата: 09.01.19 04:32
Оценка:
NI>Эти стандарты, вроде бы, нигде не говорят, что просле присваивания x становится initialized, так что на lvalue-to-rvalue conversion в +x вполне можно получить undefined behavior, если трактовать uninitialized как буквальное отсутствие у объекта x инициализации. Эта проблема упомянута в DR 240.
Ок, безусловный UB до C++14 был дефектом.

σ>>lvalue типа uint8_t ссылается на объект типа int8_t → UB при lvalue-to-rvalue conversion

σ>>В C++98/03 и 11 UB всегда.
NI>На практике — скорее всего, никогда. Для чего тогда вообще надо было упоминать про доступ через lvalue of "a type that is the signed or unsigned type corresponding to the dynamic type of the object" в [basic.lval]?

Вот из ANSI C Rationale:
> In principle, then, aliasing only need be allowed for when the lvalues all have the same type. In practice, the Committee has recognized certain prevalent exceptions:
> — The lvalue types may differ in signedness. In the common range, a signed integral type and its unsigned variant have the same representation; it was felt that an appreciable body of existing code is not ``strictly typed'' in this area.

Обрати внимание на "in the common range". Целью было разрешить читать значения из неотрицательного диапазона знаковых чисел через lvalue с любой знаковостью.
Цель позволить "реинтерпретировать" отрицательные знаковые как какие-то беззнаковые в зависимости от представления чисел на данной платформе не ставилась.

σ>>L-to-R, применённый к reinterpret_cast<std::uint8_t &>(x) имеет тип uint8_t, но значение, которое является результатом этого выражения — -1 (the value contained in the object indicated by the glvalue) — is not in the range of representable values for its type. Следовательно, the behavior is undefined.

NI> Сомневаюсь, что такая трактовка реально подразумевается (повторюсь: практическое значение имеет только подразумеваемая интерпретация правил, а не то, что получается при их буквальном прочтении).
Получающееся при буквальном прочтении UB тут реально подразумевается.
Re[52]: Зачем плюс?
От: σ  
Дата: 09.01.19 04:40
Оценка:
BFE>>>Значение указателя — адрес.
σ>>https://timsong-cpp.github.io/cppwp/n4659/basic.compound#3 :
σ>>Every value of pointer type is one of the following:
σ>> — a pointer to an object or function (the pointer is said to point to the object or function), or
σ>> — a pointer past the end of an object ([expr.add]), or
σ>> — the null pointer value ([conv.ptr]) for that type, or
σ>> — an invalid pointer value.

BFE>И что? Да, указатель указывает на объект, функцию, конец объект или имеет нулевое значение или невалидное значение.


BFE>Из 7.6.2.1/3: речь про операцию взятия адреса:

BFE>

BFE>if the type of the expression is T, the result has type “pointer to T” and is a prvalue that is the address of
BFE>the designated object
(6.6.1) or a pointer to the designated function.


Надо исправить.
Открой Issue тут https://github.com/cplusplus/draft, типа https://github.com/cplusplus/draft/issues/2311
Ну или можешь сразу PR заслать с заменой "the address of the designated object ([intro.memory]) or a pointer to the designated function" на "a pointer to the designated object or function".
Отредактировано 09.01.2019 7:37 σ . Предыдущая версия . Еще …
Отредактировано 09.01.2019 7:27 σ . Предыдущая версия .
Re[53]: Зачем плюс?
От: B0FEE664  
Дата: 09.01.19 09:21
Оценка:
Здравствуйте, σ, Вы писали:

σ>Надо исправить.

Зачем?
И каждый день — без права на ошибку...
Re[54]: Зачем плюс?
От: σ  
Дата: 09.01.19 09:27
Оценка:
σ>>Надо исправить.
BFE>Зачем?
Затем, что это некорректный wording.
Re[55]: Зачем плюс?
От: B0FEE664  
Дата: 09.01.19 09:42
Оценка:
Здравствуйте, σ, Вы писали:

σ>Затем, что это некорректный wording.

Почему вы считаете, что эта формулировка не корректная?
И каждый день — без права на ошибку...
Re[56]: Зачем плюс?
От: σ  
Дата: 09.01.19 09:43
Оценка:
σ>>Затем, что это некорректный wording.
BFE>Почему вы считаете, что эта формулировка не корректная?
Потому что похожую формулировку для указателя this пофиксили https://github.com/cplusplus/draft/pull/2319
Я же скидывал ссылку на issue.
Re[57]: Зачем плюс?
От: B0FEE664  
Дата: 09.01.19 10:48
Оценка:
Здравствуйте, σ, Вы писали:

σ>>>Затем, что это некорректный wording.

BFE>>Почему вы считаете, что эта формулировка не корректная?
σ>Потому что похожую формулировку для указателя this пофиксили https://github.com/cplusplus/draft/pull/2319
σ>Я же скидывал ссылку на issue.

Так там другой контекст. Если я правильно помню, адрес соответствующий this может меняться внутри одного и того же объекта в отличии от адреса объекта размещённого в памяти.
И каждый день — без права на ошибку...
Re[54]: Зачем плюс?
От: σ  
Дата: 27.01.19 05:50
Оценка:
NI>Примерно полтора года назад данные правила вместе с примером кода разбирались на рефлекторе комитета по стандартизации, разъяснения давал автор этих правил — Ричард Смит (обсуждение закрытое, так что ссылку дать не смогу).

А цитировать разве можно закрытые обсуждения?
Re[55]: Зачем плюс?
От: N. I.  
Дата: 28.01.19 13:41
Оценка:
σ:

σ>А цитировать разве можно закрытые обсуждения?


Когда мне предоставили туда доступ, меня не заставляли принимать какое-либо формальное NDA, а только просили не разглашать конфиденциальную информацию и не править их вики. Исчерпывающего определения того, какую инфу считать конфиденциальной, предоставлено не было, так что, видимо, мне это полагается определять самому на глазок То, что я процитировал, вряд ли является какой-то военной тайной, поэтому в данном случае я не видел смысла выпрашивать у Смита разрешение на цитирование (тратя своё и его время на никому ненужные формальности). В конце концов, если бы он нормально сформулировал правила, мне бы вообще не пришлось обращаться за разъяснениями.
Re[56]: Зачем плюс?
От: σ  
Дата: 28.01.19 14:40
Оценка:
σ>>А цитировать разве можно закрытые обсуждения?
NI>Когда мне предоставили туда доступ, меня не заставляли принимать какое-либо формальное NDA, а только просили не разглашать конфиденциальную информацию и не править их вики. Исчерпывающего определения того, какую инфу считать конфиденциальной, предоставлено не было, так что, видимо, мне это полагается определять самому на глазок
Я так понимаю, если переписка не публичная и не дано явного разрешения цитировать, то этого делать нельзя.
  Скрытый текст
Попытался недавно процитировать всего пару предложений из рефлектора на SO. Менее чем через 20 минут объявился автор цитаты с комментарием (не буквально, по смыслу) "Какого хрена?"
Re[57]: Зачем плюс?
От: N. I.  
Дата: 28.01.19 17:39
Оценка:
σ:

σ>Я так понимаю, если переписка не публичная и не дано явного разрешения цитировать, то этого делать нельзя.


Мне всё равно, в общем-то. Моё цитирование никому не наносит какой-либо реальный ущерб (скажем, если бы я опубликовал email-ы участников закрытых обсуждений или пароли для доступа к внутренним документам комитета, это действительно было бы свинством с моей стороны), а до конспираторских причуд комитетчиков мне дела нет. Если мне закроют доступ, жалеть не буду.

  Скрытый текст
σ>Попытался недавно процитировать всего пару предложений из рефлектора на SO. Менее чем через 20 минут объявился автор цитаты с комментарием (не буквально, по смыслу) "Какого хрена?"

Любопытно было бы взглянуть на эту чувствительную особу
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.