я читал этот вопрос здесь о решении порядка байтов и первый ответ несколько озадачил меня.
Код, используемый для определения больших порядков байтов, выглядит следующим образом:
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
Мой вопрос как компилятор решает, какой тип использовать для этого массива шестнадцатеричных цифр? Потому что технически он одинаково хорошо подходит как для uint32_t
или это char[4]
,
Почему бы просто не сохранить его в char[4]
и пропустить union
?
Есть ли какое-то преимущество union
вот чего я не вижу? Я знаю, что это называется наказанием, но я не вижу здесь его преимущества.
Мой вопрос: как компилятор решает, какой тип использовать для этого массива шестнадцатеричных цифр?
Как и в случае массивов и агрегатных классов, первый инициализатор инициализирует первый член; в этом случае i
, (Конечно, в отличие от этих вещей, не имеет смысла иметь более одного инициализатора).
Почему бы просто не сохранить его в char [4] и пропустить объединение? Есть ли здесь какое-то преимущество союза, которого я не вижу?
Цель этого состоит в том, чтобы инициализировать 4-байтовое целое число, а затем использовать char
массив для проверки отдельных байтов для определения порядка памяти. Если самый значимый байт (0x01
) сохраняется в первом байте, затем система является «старшим порядком байтов»; в противном случае это «little-endian» (или, возможно, что-то незнакомое).
Исходный стандарт C позволял назначать значение только первому элементу объединения. Это означает: 0x1020304 присваивается «i», а не «c».
Последний стандарт C позволяет присваивать любому члену подобное:
union { ... } bint = { .c = {1,2,3,4} };
union { ... } bint2 = { .i = 0x1020304 };
Однако, как уже было сказано, если имя не указано, то значение присваивается «i».
Потому что вы хотите хранить 0x01020304
как 32-разрядное целое число без знака uint32_t i
а потом читать первый байт char c[0]
,