Re[7]: Как обойти strict aliasing rule?
От: Erop Россия  
Дата: 18.06.16 16:52
Оценка:
Здравствуйте, Eeel, Вы писали:

E>Здравствуйте, Erop, Вы писали:


E>>А где тут минус

E>>и and с чем-то не тем...
E>>Тут или какой-то хитрый рюх или 1<<32 не в то посчитался, (лучше, конечно, 1ULL<<32 писать) или ещё чего...

E>(В оригинале суффикса ull не было.)

Ясен пень, что не было, это же был псевдокод, всё-таки...

E>Но, что интересно, Clang 3.8 заменяет два независимых сложения на нечто подобное с битовыми операциями:


E>
E>        movabs  rax, -4294967296
E>        mov     rcx, rdi
E>        and     rcx, rax
E>        add     edi, esi
E>        lea     rcx, [rcx + rsi]
E>        and     rcx, rax
E>        or      rdi, rcx
E>        mov     rax, rdi
E>        ret
E>


Ну так же предупреждал, что так, скорее всего, быстрее на актуальный x86
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как обойти strict aliasing rule?
От: flаt  
Дата: 18.06.16 18:56
Оценка:
Здравствуйте, Eeel, Вы писали:

E>По сути, это union. Но, насколько я понимаю, через union по стандарту C++ этого делать нельзя, так как это нарушение strict aliasing и UB (записывать один тип, а читать другой, несовместимый, тип).


Объясните мне, пожалуйста, а для чего ещё union, в таком случае? И как же раньше жили с LARGE_INTEGER?
Re[2]: Как обойти strict aliasing rule?
От: T4r4sB Россия  
Дата: 19.06.16 02:05
Оценка: 4 (1) +1
Здравствуйте, flаt, Вы писали:

F>Объясните мне, пожалуйста, а для чего ещё union, в таком случае?


Чтобы экономно хранить данные разных типов при условии, что они не нужны одновременно.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: Как обойти strict aliasing rule?
От: alexanius  
Дата: 20.06.16 13:47
Оценка:
Здравствуйте, placement_new, Вы писали:

_>Здравствуйте, Eeel, Вы писали:


E>>По сути, это union. Но, насколько я понимаю, через union по стандарту C++ этого делать нельзя, так как это нарушение strict aliasing и UB (записывать один тип, а читать другой, несовместимый, тип).


_>Strictly speaking, reading a member of a union different from the one written to is undefined in ANSI/ISO C99 except in the special case of type-punning to a char*, similar to the example below: Casting to char*. However, it is an extremely common idiom and is well-supported by all major compilers. As a practical matter, reading and writing to any member of a union, in any order, is acceptable practice.


_>http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html


А вот тут один интересный момент. В стандарте не говорится что это UB. Более того, там есть сноска в которой утверждается что в подобной ситуации происходит реинтерпретация данного участка памяти. По идее с точки зрения strict-aliasing здесь тоже всё должно быть нормально.

6.5.2.3 Structure and union members

95) If the member used to read the contents of a union object is not the same as the member last used to
store a value in the object, the appropriate part of the object representation of the value is reinterpreted
as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type
punning’’). This might be a trap representation.


Прошу поправить если я не прав.

PS. да, но всё равно union так лучше не использовать по многим причинам. Как вариант решения проблемы — memcpy или memmove.
Re[3]: Как обойти strict aliasing rule?
От: Eeel Россия  
Дата: 20.06.16 14:09
Оценка:
Здравствуйте, alexanius, Вы писали:

A>А вот тут один интересный момент. В стандарте не говорится что это UB. Более того, там есть сноска в которой утверждается что в подобной ситуации происходит реинтерпретация данного участка памяти. По идее с точки зрения strict-aliasing здесь тоже всё должно быть нормально.


A>

A>6.5.2.3 Structure and union members
A>...

Это секция стандарта C99 ("чистого си"), а не C++. Насколько я понимаю, в C++ этот момент отличается (что плохо).

В C++ там есть только оговорка насчет структур с одинаковым префиксом.

  C++ 14 9.5.1
In a union, at most one of the non-static data members can be active at any time, that is, the value of at
most one of the non-static data members can be stored in a union at any time. [ Note: One special guarantee
is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout
structs that share a common initial sequence (9.2), and if an object of this standard-layout union type
contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of
standard-layout struct members; see 9.2. — end note ]...

struct A
{
    int a;
    int b;
    double c;
};
struct B
{
    int a;
    int b;
    float c;
};
union Foo
{
    A a;
    B b;
};
Foo foo;

Здесь допустимо записать foo.a.a и foo.a.b, и прочитать, соответственно, foo.b.a и foo.b.b.
Отредактировано 27.06.2016 18:09 S. Schlongberg . Предыдущая версия . Еще …
Отредактировано 21.06.2016 9:56 S. Schlongberg . Предыдущая версия .
Отредактировано 21.06.2016 9:56 S. Schlongberg . Предыдущая версия .
Отредактировано 21.06.2016 9:52 S. Schlongberg . Предыдущая версия .
Отредактировано 20.06.2016 14:18 S. Schlongberg . Предыдущая версия .
Re[4]: Как обойти strict aliasing rule?
От: alexanius  
Дата: 20.06.16 14:18
Оценка:
Здравствуйте, Eeel, Вы писали:

E>Здравствуйте, alexanius, Вы писали:


A>>А вот тут один интересный момент. В стандарте не говорится что это UB. Более того, там есть сноска в которой утверждается что в подобной ситуации происходит реинтерпретация данного участка памяти. По идее с точки зрения strict-aliasing здесь тоже всё должно быть нормально.


A>>

A>>6.5.2.3 Structure and union members
A>>...


E>Это секция стандарта C99 ("чистого си"), а не C++. Насколько я понимаю, в C++ этот момент отличается (что плохо).


Это 9899:201x, т.е. черновик C11. Но я даже могу более интересную цитаты из старого черновика привести. Вот, например, цитата из 9899:TC2 (черновик C99)

6.5.2.3 Structure and union members

EXAMPLE 3
The following is a valid fragment:

union {
struct {
int alltypes;
} n;

struct {
int type;
int intnode;
} ni;

struct {
int type;
double doublenode;
} nf;
} u;

u.nf.type = 1;
u.nf.doublenode = 3.14;
/* ... */
if (u.n.alltypes == 1)
if (sin(u.nf.doublenode) == 0.0)
/* ... */


Вообще это действительно один из очень неприятных моментов стандарта, который прописан довольно туманно, и с которым постоянно возникают проблемы.
Re[5]: Как обойти strict aliasing rule?
От: alexanius  
Дата: 20.06.16 14:20
Оценка:
Здравствуйте, alexanius, Вы писали:

A>Здравствуйте, Eeel, Вы писали:


E>>Здравствуйте, alexanius, Вы писали:


A>>>А вот тут один интересный момент. В стандарте не говорится что это UB. Более того, там есть сноска в которой утверждается что в подобной ситуации происходит реинтерпретация данного участка памяти. По идее с точки зрения strict-aliasing здесь тоже всё должно быть нормально.


A>>>

A>>>6.5.2.3 Structure and union members
A>>>...


E>>Это секция стандарта C99 ("чистого си"), а не C++. Насколько я понимаю, в C++ этот момент отличается (что плохо).


A>Это 9899:201x, т.е. черновик C11. Но я даже могу более интересную цитаты из старого черновика привести. Вот, например, цитата из 9899:TC2 (черновик C99)


Извиняюсь, ступил и не увидел что ТС про C++ говорит.
Re[2]: Как обойти strict aliasing rule?
От: Mr.Delphist  
Дата: 22.06.16 10:46
Оценка: +1 -2
Здравствуйте, Videoman, Вы писали:

V>Интересно, вопрос вроде по тойже теме, а тут:

V>
V>struct Foo
V>{
V>    union
V>    {
V>        std::uint32_t value[2];

V>        struct 
V>        {
V>            std::uint32_t value32Lo;

V>            std::uint32_t value32Hi;           
V>        };
V>    };
V>};
V>


V>тут такая же проблема с выравниванием, или, из-за того что типы одинаковые, гарантий больше ?


По идее, гарантий никаких. В массиве данные идут подряд (чтобы работала арифметика указателей через sizeof), а в структуре может быть паддинг на 8 байт.

P.S. Товарищи минусующие, не стесняйтесь оставлять свою точку зрения! Ссылки на Стандарт караются плюсом в карму
Отредактировано 08.07.2016 9:01 Mr.Delphist . Предыдущая версия .
Re: Как обойти strict aliasing rule?
От: jazzer Россия Skype: enerjazzer
Дата: 26.06.16 17:01
Оценка:
Здравствуйте, Eeel, Вы писали:

А можно узнать, что за глубокая идея стоит за стиранием своих сообщений? Чтоб геморроя читающим добавить? Восстанови, плиз.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Как обойти strict aliasing rule?
От: uzhas Ниоткуда  
Дата: 28.06.16 08:53
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>По идее, гарантий никаких. В массиве данные идут подряд (чтобы работала арифметика указателей через sizeof), а в структуре может быть паддинг на 8 байт.


кстати, интересное наблюдение
какие есть гарантии, что value32Hi ляжет точно в value[1] ?
Re[4]: Как обойти strict aliasing rule?
От: watchmaker  
Дата: 28.06.16 17:32
Оценка: -1
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, Mr.Delphist, Вы писали:


MD>>По идее, гарантий никаких. В массиве данные идут подряд (чтобы работала арифметика указателей через sizeof), а в структуре может быть паддинг на 8 байт.


U>кстати, интересное наблюдение

U>какие есть гарантии, что value32Hi ляжет точно в value[1] ?

Предлагаю посмотреть на проблему «массив vs. структура» с этой стороны:

if a is an expression of type cv std::complex<T>* and the expression a[i] is well-defined for an integer expression i, then:
— reinterpret_cast<cv T*>(a)[2*i] shall designate the real part of a[i], and
— reinterpret_cast<cv T*>(a)[2*i + 1] shall designate the imaginary part of a[i].

И попробовать придумать реализацию, где одновременно и std::complex<uint32_t> работает, и value32Hi не попадает в value[1].
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.