Печать числа в двоичном формате всегда печатает в нормальной форме (БОЛЬШОЙ Endian), даже если мой компьютер Little Endian?
Прежде всего, я использую пользовательскую функцию под названием showBin()
это вывело бы двоичное число из целого числа. Как вы можете видеть, эта функция проверяет каждый бит данного числа от самой правой позиции до самой левой позиции (от MSB до LSB).
Использую Union
с двумя членами, я сохранил 512 в его первом члене(short unsigned int a)
,(мы знаем, что обычно (в Big Endian) двоичный код 512 равен 0000 0010 0000 0000) и на следующем шаге попытался напечатать значения массива c[0]
а также c[1]
Поскольку моя машина имеет формат Little Endian, она четко выдает: 0 2, теперь это означает, что под капотом (в памяти) бинарный файл хранится как: 0000 0000 0000 0010
Но когда я печатаю значение a
с помощью showBin()
это показывает 0000 0010 0000 0000, что в обычном (Big Endian) способе, почему это не выводит в формате Little Endian i, e 0000 0000 0000 0010???? Даже если мой компьютер хранит число в BIG Endian, тогда он должен вывести 2 0 правильно?????? Я действительно в замешательстве..????.. может кто-нибудь Пожалуйста, объясните это поведение простыми словами.
void showBin(unsigned short int a);
int main()
{
union myun
{
short unsigned int a; //2 bytes
char c[2]; //2 bytes
};
union myun som;
som.a=512;
printf("%hu %hu \n",som.c[0],som.c[1]);
printf("512 in Binary:");showBin(som.a);printf("\n");//Doubt here..
return 0;
}
void showBin(unsigned short int a)
{
int i;
unsigned short int mask=0;
unsigned short int res=0;
for(i=15;i>=0;i--)
{
mask=0;//resetting imp..
mask=mask | (1<<i);
res=a & mask;
(res==0)?printf("0"):printf("1");
}
}
2 ответа
Ваша реализация showBin
не зависит от порядка байтов
Считайте ваше целое число без знака mask
смещение влево на единицу будет точно таким же, как умножение на два на всех платформах. На самом деле, C и C++ построены таким образом, что endianess не влияет на то, что вы делаете с кодом, соответствующим стандартам.
Если вы хотите испытать постоянство, вам нужно сделать что-то, что не определено в стандартах C и C++, но на самом деле довольно просто:
int x = 42;
char* m = (char*)&x;
for(size_t i = 0; i < sizeof(x); ++i) {
unsigned char value = (unsigned char)m[i];
// do something to your bytes - e.g. use showBin to display the binary representation
}
Операции shift и mask не выявляют порядковый номер системы. Только порядок байтов в памяти указывает на порядок байтов.
Для C endianness - это в основном деталь реализации, которая абстрагируется от вас. Инструкции, которые ваша цель, вероятно, использует, принимают регистры в качестве операндов, и эти регистры логически один в один с int
тип (ы). Таким образом, операции сдвига и маски обычно являются родными. Endianness вступает в игру с тем, как эта цель выполняет LOAD
или же STORE
операция (чтение / запись регистров из / в память).
Независимо от порядкового номера вашей цели, оператор левого смещения <<
закончится компиляцией в собственную инструкцию левого сдвига. И это смещение влево будет работать так же, как вы думаете (смещение в сторону более значимых битов). Но не называйте это "большим порядком байтов", потому что на самом деле это не вопрос порядков байтов.
Endianness - это не "Как мне написать эту цифру на доске?", А "Как мне сериализовать эти данные?"
Из википедии (выделено мое):
В вычислениях память обычно хранит двоичные данные, организуя их в 8-битные единицы (байты). Когда слово данных использует несколько таких блоков, порядок сохранения этих байтов в памяти становится важным. Термины endian и endianness относятся к тому, как байты слова данных упорядочены в памяти.