- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
union bitdata {
struct {
unsigned int bit1 : 1;
unsigned int bit2 : 1;
unsigned int bit3 : 1;
unsigned int bit4 : 1;
unsigned int bit5 : 1;
unsigned int bit6 : 1;
unsigned int bit7 : 1;
unsigned int bit8 : 1;
};
unsigned char byte;
} first_byte, second_byte;
<...>
for ( j = 0; j < bytes_count; j++ ) {
unsigned char t;
ret = gzread( gz_fd, &t, sizeof( t ) );
if ( ret != sizeof( t ) ) {
printf( "Failed to read file %s: %s\n", argv[i], strerror( errno ) );
gzclose( gz_fd );
return EXIT_FAILURE;
}
first_byte.byte = t;
second_byte.byte = ready_bytes[j];
first_byte.bit1 = first_byte.bit1 == 0 && second_byte.bit1 == 0 ? 0 : 1;
first_byte.bit2 = first_byte.bit2 == 0 && second_byte.bit2 == 0 ? 0 : 1;
first_byte.bit3 = first_byte.bit3 == 0 && second_byte.bit3 == 0 ? 0 : 1;
first_byte.bit4 = first_byte.bit4 == 0 && second_byte.bit4 == 0 ? 0 : 1;
first_byte.bit5 = first_byte.bit5 == 0 && second_byte.bit5 == 0 ? 0 : 1;
first_byte.bit6 = first_byte.bit6 == 0 && second_byte.bit6 == 0 ? 0 : 1;
first_byte.bit7 = first_byte.bit7 == 0 && second_byte.bit7 == 0 ? 0 : 1;
first_byte.bit8 = first_byte.bit8 == 0 && second_byte.bit8 == 0 ? 0 : 1;
ready_bytes[j] = first_byte.byte;
}
Всё еще не можем понять, зачем в конце тернарник. Всё остальное уже не смущает.
Кто-то прогуливал мат логику.
З.Ы. Тут же просто first_byte.byte |= second_byte.byte?
Какой багор )))
С одной стороны на лабу не похоже.
>return EXIT_FAILURE;
> strerror( errno )
И всё довольно вменяемо.
С другой, нумерация bit1 с единицы и реализация побитовой илишни руками.
А я вот битовые структуры вообще не умею юзать... Мне проще через & и | побитоёбить.
Но в пределах одного ABI работать будет, конечно.
- bit fields are allocated from right to left
- bit-fields must be contained in a storage unit appropriate for its declared type
- bit-fields may share a storage unit with other struct / union members
Что такое "may share"? Т.е. при каких-то условиях могут и в разные юниты попасть?
Блядь, и это формальная спецификация?
Т.е. 16-битный storage unit вполне так appropriate для 8-битного поля. Но только если рядом есть другие 16-битные поля, иначе он уже не особо appropriate (по крайней мере для gcc). Где блядь об этом написано?
Значит, неупакованный вариант можно использовать только для временного хранения.
Именно так. Он походу пытается добиться какого-то баланса между пирфомансом и размером, из-за этого алгоритм совсем неочевидный.
И получается что вменяемого, документированного ABI у сишки для x86_64 нет. Всё работает только за счёт того, что конпеляторы подстраиваются под своих старших собратьев.
Помоему это заивисит от проца
Видимо, производители компиляторов поддерживают этот хак, иначе куча программ сломается.
Finally, one of the changes from C90 to C99 was to remove any restriction on accessing one member of a union when the last store was to a different one. The rationale was that the behaviour would then depend on the representations of the values. Since this point is often misunderstood, it might well be worth making it clear in the Standard.
[...]
To address the issue about "type punning", attach a new footnote 78a to the words "named member" in 6.5.2.3#3: 78a If the member used to access 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.
Я про возможный хак для использования таких множеств вместо битовых полей. Типа:
Во Фрипаскаль добавили симметричную разность (><, экв. xor) и проверку на подмножество и надмножество (<= и >=).
Есть же в паскакале obsolete для такого. Или на крайний случай можно кастануть.
Так?
Хотя при желании можно запихать, конечно. Только это будет просто inflate без gzopen/gzread и прочего нинужного обвеса.
каким образом в битах оказываются правильные значения?
я вижу юнион, но внутри же у него int, почему каждый из них занимает ровно один бит, а не 32 или сколько там предусмотрено платформой?
upd:
это указание длины что ли?
так можно было?
в пизду, будут джаваскриптером
32 бита инт небось для выравнивания выбран.
https://en.cppreference.com/w/c/language/bit_field
Считай это сахарок над побитовыми оперециями, нопремер first_byte.bit2 = 1 скомпилица в first_byte.byte |= 0x02
Выравнивание storage unit'а для битовых полей соответствует тому типу, который попросили. В данном случае unsigned int. Т.е. эта структура, судя по всему, будет состоять из одного юнита на 4 байта из которых только 8 бит юзаются под битовые поля.
Чтобы первые пол года работать правильно, а потом выкинуть половину твоей программы в самый неожиданный момент
У меня в контроллерах нет никакого понятия "root privileges", поэтому я за контроллеры.
https://www.bleepingcomputer.com/news/security/new-linux-sudo-flaw-lets-local-users-gain-root-privileges/
хотя подобные дыры наверняка еще будут.
Для guest6 что-то слишком свежая новость... Я думала, что он что-нибудь из 90х принёс.