+133
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
#ifndef ORDER32_H
#define ORDER32_H
#include <limits.h>
#include <stdint.h>
#if CHAR_BIT != 8
#error "unsupported char size"
#endif
enum
{
O32_LITTLE_ENDIAN = 0x03020100ul,
O32_BIG_ENDIAN = 0x00010203ul,
O32_PDP_ENDIAN = 0x01000302ul
};
static const union { unsigned char bytes[4]; uint32_t value; } o32_host_order =
{ { 0, 1, 2, 3 } };
#define O32_HOST_ORDER (o32_host_order.value)
#endif
Говнокод из http://stackoverflow.com/questions/2100331/c-macro-definition-to-determine-big-endian-or-little-endian-machine
Мало того, что писать в один тип из юниона и потом читать из другого это UB, так еще компилятор (в случае GCC) из
int main(void)
{return O32_HOST_ORDER == O32_LITTLE_ENDIAN;}
нагенерирует код
main:
xor eax, eax
cmp DWORD PTR o32_host_order[rip], 50462976
sete al
ret
o32_host_order:
.byte 0
.byte 1
.byte 2
.byte 3
т.е. всякий раз, когда надо узнать endianess, мы лезем в константную статическую переменную и сравниваем ее с константой
Запостил: j123123,
08 Апреля 2014
bormand 08.04.2014 20:41 # +2
ЩИТО? Можно цитату из стандарта?
j123123 08.04.2014 20:48 # +1
Page 38, 6.2.6.1
Change paragraph 7 to:
When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.
WGH 08.04.2014 21:48 # +2
Так мы по этим unspecified values и хотим понять, какая же endianness. Это не то же самое, что UB.
j123123 08.04.2014 22:13 # +3
А если у нас будут еще и структуры в юнионе, в структурах может быть разный alignment на разных компиляторах (и даже разных таргетах одного компилятора) и соответственно там могут быть дырки, всякие хитрые перекрытия полей структур, стандарт это поведение никак не регламентирует
bormand 08.04.2014 22:17 # +1
Dummy00001 08.04.2014 23:40 # −1
... с точки зрения абстрактного ISO стандарта. а с точки зрения конкретной реализации (железо + OS + этц) это вполне определенная вещь. потому что бы иначе ни одна ось, писаная на С не забутилась бы.
погугли "sysv abi x86-64" pdf'ку.
guest 08.04.2014 23:41 # 0
Dummy00001 08.04.2014 23:46 # +1
guest 08.04.2014 23:52 # 0
WGH 08.04.2014 23:50 # 0
guest 08.04.2014 23:52 # 0
WGH 08.04.2014 23:57 # 0
А так бы ведь пересели с асма на что-то по типу LLVM IR. Портабельно же.
guest 09.04.2014 00:04 # 0
bormand 09.04.2014 05:24 # 0
guest 09.04.2014 05:29 # 0
Кросскомпиляцию можно забыть?
bormand 09.04.2014 06:16 # 0
Ну тесты соберешь кросскомпилером и на таргете прогонишь. Если там найдется чем их запустить :)
3_dar 05.11.2020 23:46 # 0
bormand 06.11.2020 08:54 # +1
guest6 06.11.2020 10:22 # +1
bormand 06.11.2020 10:55 # +1
guest6 06.11.2020 10:58 # +2
3_dar 06.11.2020 19:44 # 0
j123123 09.04.2014 01:17 # 0
Вообще это какая-то мутная и неоднозначная фразочка.
Если у нас есть юнион типа
Черт знает что
laMer007 09.04.2014 01:53 # 0
в be.bytes[0] или be.bytes[5] в зависимости от индусности машины будет неизвестное значение после присвоения be.value = 0;
Что намекает нам ещё раз вопреки практике о бесполезности присвоений и чтений в\из разных членов, тк нет гарантии сохранения нетронутого байта в первозданном виде (в том виде, что до присвоения be.value = 0;).
Прозаично, но сишники обожают юзать юнионы для разруливания strict aliasing и записи по частям.
WGH 09.04.2014 12:12 # 0
Возможно, вы имели в виду be.bytes[3]?
bormand 09.04.2014 12:16 # +2
j123123 08.04.2014 20:49 # 0
j123123 08.04.2014 20:54 # 0
В некоторых случаях этот самый юнион используется как раз для выравнивания, чтобы не использовать гцц-шные атрибуты и прагма пак (их в стандарте точно нет) https://github.com/radare/radare2/blob/086fc30e3bee81cee3eb7678757443beda46d42a/shlr/sdb/src/cdb_make.c#L13
bormand 08.04.2014 20:55 # +2
Ок, будем знать :)
kipar 09.04.2014 00:05 # 0
[quote]The behavior of type punning with union changed from C89 to C99. The behavior in C99 is the same as C11.
As Wug noted in his answer, type punning is allowed in C99 / C11. An unspecified value that could be a trap is read when the union members are of different size.[/quote]
Другие отвечают что примечание не имеет юридической силы.
WGH 09.04.2014 00:10 # 0
WGH 08.04.2014 23:11 # −2
http://gcc.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A {%22labels%22%3Atrue%2C%22directives%22% 3Atrue%2C%22commentOnly%22%3Atrue%2C%22i ntel%22%3Atrue}%2C%22compilers%22%3A[{%22sourcez%22%3A%22MQSwdgxgNgrgJgUwAQB4 DOAXO4MDoAWAfAFDE5IhoD6UIGGUCVCY2AhmABQB uA9iHACUSAN7EkEpDDAheYUeMkSAkNLQgA5mARwk EfGwBOSAEYBPDAjQBtACwBdANyKlEmDgDMAJioYk 3NlgEZyUAXyRGJABeUQAGAA9YgEYAGiQE2K80jI9 sxNtQ5xckQwQMGEN5DNtYj0zk6JjGXACg51DScko qE01mVhAOHn4hBSVpWXkxVyRVMHUtHT0DY3NLGwc QmalPHz9WmGDi8JNkGJFqvNqrrPTEpMLSJVLyyrv YmrqvBqiY05bAod2kAAA%22%2C%22compiler%22 %3A%22%2Fusr%2Fbin%2Fclang%2B%2B%22%2C%2 2options%22%3A%22-O3%20%22}]}
bormand 08.04.2014 23:33 # +1
WGH 08.04.2014 23:36 # 0
Должно помочь.
3_dar 05.11.2020 23:48 # 0
guest 08.04.2014 23:38 # 0
3_dar 05.11.2020 23:49 # 0
Vindicar 09.04.2014 08:12 # +3
WGH 09.04.2014 12:16 # +2
У меня иррациональная неприязнь к сокращалкам ссылок, даже если они, как например здесь, уместны.
guest 09.04.2014 15:41 # 0
j123123 09.04.2014 08:17 # 0
С армами и gcc вообще интересная ситуация
https://en.wikipedia.org/wiki/Endianness#Bi-endian_hardware
Some architectures (including ARM versions 3 and above, PowerPC, Alpha, SPARC V9, MIPS, PA-RISC, SuperH SH-4 and IA-64) feature a setting which allows for switchable endianness in data segments, code segments or both. This feature can improve performance or simplify the logic of networking devices and software. The word bi-endian, when said of hardware, denotes the capability of the machine to compute or pass data in either endian format.
Ну и в самом гцц есть опции для выставления режима http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
-mlittle-endian
Generate code for a processor running in little-endian mode. This is the default for all standard configurations.
-mbig-endian
Generate code for a processor running in big-endian mode; the default is to compile code for a little-endian processor.
-mwords-little-endian
This option only applies when generating code for big-endian processors. Generate code for a little-endian word order but a big-endian byte order. That is, a byte order of the form ‘32107654’. Note: this option should only be used if you require compatibility with code for big-endian ARM processors generated by versions of the compiler prior to 2.8. This option is now deprecated.
bormand 09.04.2014 08:49 # +1
И мальчиков и девочек любит? На ходу что-ли менять умеет?
j123123 09.04.2014 09:00 # +1
A2.7 Endian support
WGH 09.04.2014 12:16 # +2
bormand 09.04.2014 12:34 # 0
WGH 09.04.2014 12:36 # +2
Psionic 11.04.2014 17:23 # 0
WGH 11.04.2014 17:25 # +1
bormand 11.04.2014 17:39 # 0
roman-kashitsyn 11.04.2014 17:42 # +1
WGH 11.04.2014 21:30 # 0
FreeBSD clang version 3.3 вообще отказался это собирать, сказав:
constexpr function never produces a constant expression.
note: read of member 'value' of union with active member 'bytes' is not allowed in a constant expression
Компиляторы, которые есть в списке gcc.godbolt.org, все-таки собрали это.
Несмотря на наличие constexpr, ICC все равно нагенерировал сравнение: http://goo.gl/aGj8zF
С GCC под ARM похожая история: http://goo.gl/e9ePxW Я не очень умею читать ассемблер на ARM, но вроде все выходит так:
Сперва по кусочкам (!) {0x01, 0x02, 0x03, 0x04} загружается в регистр r3 (см. инструкции BFI, Bit Field Insert), затем 0x4030201 грузится за два захода в r4 через пару mov и movt (ARM, походу, иначе не умеет), и потом они сравниваются.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/Cjagdjbf.html
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/Cihcdbca.html
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/Cjagchif.html
guest 11.04.2014 21:39 # 0
Ты не поверишь, но он не обязан генерировать константу.
WGH 11.04.2014 21:46 # 0
ICC: constant value is not known
GCC под ARM тоже сломался:
in constexpr expansion of ‘is_little_endian()’
error: accessing ‘lol_t::value’ member instead of initialized ‘lol_t::bytes’ member in constant expression
Походу, компиляторы проверяют constexpr на ошибки только при раскрытии.
Edit: Только шланг молодец, сразу нашел подвох.
3_dar 05.11.2020 23:56 # 0
j123123 06.11.2020 00:00 # 0
3_dar 05.11.2020 23:51 # 0
bormand 06.11.2020 08:54 # 0
Но не факт конечно что компиляторы заморачиваются с оптимизацией каста через юнион.
gost 06.11.2020 10:22 # 0
lakrVOg 25.08.2021 05:29 # 0