Здравствуйте, 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
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Eeel, Вы писали:
E>По сути, это union. Но, насколько я понимаю, через union по стандарту C++ этого делать нельзя, так как это нарушение strict aliasing и UB (записывать один тип, а читать другой, несовместимый, тип).
Объясните мне, пожалуйста, а для чего ещё union, в таком случае? И как же раньше жили с LARGE_INTEGER?
Здравствуйте, 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.
Здравствуйте, 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.
Здравствуйте, 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)
/* ... */
Вообще это действительно один из очень неприятных моментов стандарта, который прописан довольно туманно, и с которым постоянно возникают проблемы.
Здравствуйте, 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++ говорит.
V>тут такая же проблема с выравниванием, или, из-за того что типы одинаковые, гарантий больше ?
По идее, гарантий никаких. В массиве данные идут подряд (чтобы работала арифметика указателей через sizeof), а в структуре может быть паддинг на 8 байт.
P.S. Товарищи минусующие, не стесняйтесь оставлять свою точку зрения! Ссылки на Стандарт караются плюсом в карму
Здравствуйте, Mr.Delphist, Вы писали:
MD>По идее, гарантий никаких. В массиве данные идут подряд (чтобы работала арифметика указателей через sizeof), а в структуре может быть паддинг на 8 байт.
кстати, интересное наблюдение
какие есть гарантии, что value32Hi ляжет точно в value[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].