Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Бинарные файлы, Непонятное поведение 
:(
    Опции темы
wowka19
Дата 14.12.2014, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



Код

 FILE * output = fopen("TEST.bin", "wb");

unsigned int Length = 13;
fwrite(&Length, sizeof(unsigned int), 1, output);

fclose(output);


В итоге TEST.bin весит 4 байта, что есть норма так как в моем случае sizeof(unsigned int) == 4.
Открываю файл в HEX-редакторе и вижу: "0d 00", т.е. всего два байта вместо четырех, причем неверно расположенных, ибо 13 == 00 0d.
Я же ожидал увидеть "00 00 00 0d".
Что не так?


Это сообщение отредактировал(а) wowka19 - 14.12.2014, 21:27
PM MAIL   Вверх
vol4ek
Дата 14.12.2014, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


конь в пальто
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 1.5.2011
Где: Минск

Репутация: 0
Всего: 0



посмотрел файл в WinHEX - 0D 00 00 00
PM MAIL ICQ   Вверх
wowka19
Дата 14.12.2014, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



Но "0D 00 00 00" это не 13, а 218103808. Поэтому должно быть "00 00 00 0D". Вопрос остался.
Получается я как-то неправильно кладу uint, но почему? и как правильно?

Вообще, попрошу посоветовать какую-нибудь статью на эту тему - как правильно упаковывать данные в бинарники.

Это сообщение отредактировал(а) wowka19 - 14.12.2014, 22:13
PM MAIL   Вверх
baldina
Дата 14.12.2014, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(wowka19 @  14.12.2014,  22:09 Найти цитируемый пост)
попрошу посоветовать какую-нибудь статью на эту тему

https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2
PM MAIL   Вверх
tzirechnoy
Дата 15.12.2014, 00:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



Ещё я посоветую прочитать и понять вот это: http://commandcenter.blogspot.ru/2012/04/b...er-fallacy.html
PM MAIL   Вверх
Vasya
Дата 17.12.2014, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 5.7.2003

Репутация: нет
Всего: нет



Так, к слову, на платформах интел, эсли не ошибаюсь, чтение идет задом на перед, сначала читаются последние байты, потом первые. Т.е. 0D 00 00 00 после прочтения преобразуются  в 00 00 00 DD.

Это сообщение отредактировал(а) Vasya - 17.12.2014, 22:34
PM MAIL   Вверх
feodorv
Дата 18.12.2014, 08:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(Vasya @  17.12.2014,  22:26 Найти цитируемый пост)
Т.е. 0D 00 00 00 после прочтения преобразуются  в 00 00 00 DD.

Нет. На "платформах интел" 0D 00 00 00 и есть 0x0000000D безо всяких преобразований (до чтения либо после).


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Vasya
Дата 18.12.2014, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 5.7.2003

Репутация: нет
Всего: нет



Цитата(feodorv @  18.12.2014,  08:43 Найти цитируемый пост)
Цитата(Vasya @  17.12.2014,  22:26 )
Т.е. 0D 00 00 00 после прочтения преобразуются  в 00 00 00 DD.

Нет. На "платформах интел" 0D 00 00 00 и есть 0x0000000D безо всяких преобразований (до чтения либо после). 


ок, я неправильно выразился, ничего не преобразуется, просто при записи сначала записываются младшие байты, затем старшие, поэтому 0d 00 00 00 надо трактовать как 00 00 00 0d.
PM MAIL   Вверх
wowka19
Дата 22.12.2014, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



tzirechnoy, а на русском есть подобная статья?
зы: не ругайте за незнание английского - сам знаю.
PM MAIL   Вверх
sQu1rr
Дата 22.12.2014, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: 3
Всего: 13



Цитата(wowka19 @  22.12.2014,  12:31 Найти цитируемый пост)
а на русском есть подобная статья?

Что-то приблизительно похожее есть тут. http://habrahabr.ru/post/233245/
А так гуглите "Порядок байт"
PM MAIL Skype GTalk   Вверх
feodorv
Дата 22.12.2014, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(wowka19 @  22.12.2014,  14:31 Найти цитируемый пост)
а на русском есть подобная статья?

А чем Вики не угодила? Ссылку дал baldina smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
wowka19
Дата 29.12.2014, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



Получил CRC32 в (UNSIGNED LONG). Как мне привести UNSIGNED LONG к 4 CHAR ?

Добавлено через 11 минут и 49 секунд
Ответ:
Код

unsigned long crc32 = Crc32(TYPE_AND_DATA, 17);
char * c = (char*) &crc32; //!!!
char inv[4];
for (int i = 0; i < 4; ++i) inv[i] = c[3-i]; //нужен обратный порядок для представления CRC32 чанка в PNG


Вообще я так и не понял: зачем нужен обратный(прямой) порядок байт. Почему не используют один вариант. Не смогли договориться?
PM MAIL   Вверх
konshyn
Дата 29.12.2014, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 295
Регистрация: 19.9.2013

Репутация: нет
Всего: нет



Цитата(wowka19 @  29.12.2014,  11:47 Найти цитируемый пост)
Вообще я так и не понял: зачем нужен обратный(прямой) порядок байт. Почему не используют один вариант. Не смогли договориться? 

Можно сказать и так
Из Вики:
Цитата

Термины big-endian и little-endian первоначально не имели отношения к информатике. В сатирическом произведении Джонатана Свифта «Путешествия Гулливера» описываются вымышленные государства Лилипутия и Блефуску, в течение многих лет ведущие между собой войны из-за разногласия по поводу того, с какого конца следует разбивать варёные яйца. Тех, кто считает, что их нужно разбивать с тупого конца, в произведении называют Big-endians («тупоконечники»). Споры между сторонниками big-endian и little-endian в информатике также часто носят характер т. н. «религиозных войн».[2]



--------------------
«Потому что ценность акта действия в этой стране возрастает в несколько раз».
PM MAIL Skype   Вверх
sQu1rr
Дата 29.12.2014, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: 3
Всего: 13



Цитата(wowka19 @  29.12.2014,  09:47 Найти цитируемый пост)
Как мне привести UNSIGNED LONG к 4 CHAR ?

А вы уверены что long 4 байта? или вы для своего (непереносимого) пользования?
PM MAIL Skype GTalk   Вверх
konshyn
Дата 29.12.2014, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 295
Регистрация: 19.9.2013

Репутация: нет
Всего: нет



Цитата(sQu1rr @  29.12.2014,  12:15 Найти цитируемый пост)
А вы уверены что long 4 байта? или вы для своего (непереносимого) пользования? 

Если говорить именно о типе unsigned long, то в стандарте С сказано, что значение должно быть минимум [0; 2^32 -1]. 
Не встречал ни одной платформы, где использовалось бы значение больше. А меньше не может быть, т.к. стандарт обязывает.

А вообще, Вы правы: лучше использовать такие типы, как uint8_t, ..., uint32_t, uint64_t


--------------------
«Потому что ценность акта действия в этой стране возрастает в несколько раз».
PM MAIL Skype   Вверх
sQu1rr
Дата 29.12.2014, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: 3
Всего: 13



Цитата(konshyn @  29.12.2014,  10:21 Найти цитируемый пост)
Если говорить именно о типе unsigned long, то в стандарте С сказано, что значение должно быть минимум [0; 2^32 -1]. 
Не встречал ни одной платформы, где использовалось бы значение больше.

Приду домой проверю, но вроде как на x64 8 байт. вот такие дела.
PM MAIL Skype GTalk   Вверх
konshyn
Дата 29.12.2014, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 295
Регистрация: 19.9.2013

Репутация: нет
Всего: нет



Цитата(sQu1rr @  29.12.2014,  12:44 Найти цитируемый пост)
Приду домой проверю, но вроде как на x64 8 байт. вот такие дела. 

О, Вы правы, действительно:)
Надо бы иногда проверять типы...
А то как вошло в привычку использовать uint типы, когда нужна точность в байтах, так и использую.


--------------------
«Потому что ценность акта действия в этой стране возрастает в несколько раз».
PM MAIL Skype   Вверх
DarthTon
Дата 30.12.2014, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: нет
Всего: 6



Размер long - 4 байта в винде, но 8 байт в x64 юникс-системах. Поэтому надо внимательно использовать его в кроссплатформенном коде.
PM MAIL   Вверх
wowka19
Дата 31.12.2014, 01:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



Спасибо. Учел ваши замечания:
Код

uint32_t crc32 = Crc32(TYPE_AND_DATA, 17); // 1
uint8_t * c = (uint8_t*) &crc32;
uint8_t inv[4];
for (int i = 0; i < 4; ++i) inv[i] = c[3-i]; //нужен обратный порядок для представления CRC32 чанка в PNG


1) Функция Crc32() возвращает тип ulong. Повлияет ли это на содержимое uint32_t crc32, если ulong будет больше 4 байт?
2) В последней строке я меняю порядок байт. Делаю я это чисто из практического наблюдения (в hex-редакторе увидел, что порядок не тот и поменял). Отсюда вопрос: этот код будет работать одинаково на всех платформах/компиляторах?


Это сообщение отредактировал(а) wowka19 - 31.12.2014, 01:28
PM MAIL   Вверх
konshyn
Дата 31.12.2014, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 295
Регистрация: 19.9.2013

Репутация: нет
Всего: нет



Цитата(wowka19 @  31.12.2014,  01:26 Найти цитируемый пост)
1) Функция Crc32() возвращает тип ulong. Повлияет ли это на содержимое uint32_t crc32, если ulong будет больше 4 байт?

если возвращаемое значение будет больше 2^32 - 1, то в переменную типа uint32_t будет записано обрезанное до 4 байт значение, а так не должно влиять.

Цитата(wowka19 @  31.12.2014,  01:26 Найти цитируемый пост)
2) В последней строке я меняю порядок байт. Делаю я это чисто из практического наблюдения (в hex-редакторе увидел, что порядок не тот и поменял). Отсюда вопрос: этот код будет работать одинаково на всех платформах/компиляторах?

зачем менять просто так? есть порядок байт little endian и big endian, Вам уже писали выше. если Вы хотите переносимости, то должны решить, в каком порядке хранить байты, т.к. если вы будете просто менять, то в little endian поменяете на big endian и наоборот. И тогда на платформах с разным порядком байт программа из файла будет по-разному считывать значения. 
Храните, например, все содержимое файла в Big Endian формате, и тогда Вам придется менять порядок байт только на платформах с little endian. 


--------------------
«Потому что ценность акта действия в этой стране возрастает в несколько раз».
PM MAIL Skype   Вверх
wowka19
Дата 2.1.2015, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



Почитал статью на хабре и не совсем понял.
Для уточнения/закрепления прочитанного:
Код

short s = 1000;
char * c = (char*) &s;
cout << *c;

как я понял код выше уже скомпилированный один раз на одной машине может выдавать разные результаты в зависимости машины на которой выполняется. Так?

Как я понял порядок байт задается НЕ на уровне ОС, а глубже/ниже и он неизменен. Так?
А конкретно на каком уровне он задается: на уровне прошивки BIOS или это вообще аппаратная причуда CPU?

Почему для UTF8 не важен порядок байт, ведь это многобайтная кодировка?

И как принято писать код, работающий с бинарными данными, чтобы он работал на любой машине одинаково?

Это сообщение отредактировал(а) wowka19 - 2.1.2015, 07:22
PM MAIL   Вверх
DarthTon
Дата 3.1.2015, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: нет
Всего: 6



Цитата

Как я понял порядок байт задается НЕ на уровне ОС, а глубже/ниже и он неизменен. Так?
А конкретно на каком уровне он задается: на уровне прошивки BIOS или это вообще аппаратная причуда CPU?

Это зависит от ЦП. Вся линейка х86 и х86-64 процессоров little-endian. Есть так же процессоры которые поддерживают оба порядка байт.
Цитата

Почему для UTF8 не важен порядок байт, ведь это многобайтная кодировка?

В ней каджый байт сам по себе, endianness же влият на порядок байт в цельных машинных словах.
Цитата

И как принято писать код, работающий с бинарными данными, чтобы он работал на любой машине одинаково?

Проверять endianness после прочтения данных, и при необходимости конвертировать в нужный порядок. Однако, если вы не собираетесь запускать свои программы на всях там SPARC, IBM POWER и прочих RISC'ах, этим можно не заморачиваться.
PM MAIL   Вверх
wowka19
Дата 6.1.2015, 09:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



Цитата(DarthTon @  3.1.2015,  22:51 Найти цитируемый пост)
Проверять endianness после прочтения данных, и при необходимости конвертировать в нужный порядок. Однако, если вы не собираетесь запускать свои программы на всях там SPARC, IBM POWER и прочих RISC'ах, этим можно не заморачиваться.

Нет. Я неправильно выразился. Уточню:
1. Как программе самостоятельно определить byte order текущей машины, чтобы потом правильно интерпретировать данные?
На ум приходит что-то вроде этого:
Код

uint16_t test_data = 1;
uint8_t * p_first_byte = (uint8_t*) &test_data;
if (*p_first_byte) // "01 00"
{
    // сейчас на текущей машине - little-endian,
    // но мне нужно писать в PNG, в котором принят big-endian,
    // поэтому я буду переставлять байты
}
else // "00 01"
{
    // сейчас на текущей машине - big-endian,
    // и поэтому в этот раз эта программа просто запишет данные в PNG-файл,
    // ничего не меняя
}

Но, подозреваю, что это костыль/велосипед и есть давно принятый де факто стандарт. Как пишите вы?

2. Как менять порядок байт без велосипедостроения? Какие есть устоявшиеся варианты, какие из них самые быстрые?

Спасибо за помощь!

Это сообщение отредактировал(а) wowka19 - 6.1.2015, 09:05
PM MAIL   Вверх
baldina
Дата 6.1.2015, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



и про определение, и про преобразование
http://stackoverflow.com/questions/1001307...-in-a-c-program
PM MAIL   Вверх
wowka19
Дата 6.1.2015, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



baldina, спасибо, но стало еще хуже:

1. топовое решение в по вашей ссылке:
Код

int is_big_endian(void)
{
    union {
        uint32_t i;
        char c[4];
    } bint = {0x01020304};

    return bint.c[0] == 1; 
}

Какое-то оно чересчур избыточно.
Зачем 4 байта когда и двух хватит?
Зачем такая абсурдная инициализация = 0x01020304, разве просто единицы (= 1) не хватит?
Да и если позанудствовать, то странно видеть в таком коде uint32_t и char[4] вместе, ведь они не всегда соразмерно, а это может быть критичным.

2. на втором месте такой вариант:
Код

if ( htonl(47) == 47 ) {
  // Big endian
} else {
  // Little endian.
}

Кажется это то что я искал. На самом деле мне не нужно знать какой порядок на машине, мне подойдет функция вроде htonl/ntohl, скрывающая всю кухню преобразований. Вот только это функции не из стандартной библиотеки, а какие-то юниксовые вроде. Замечу, что я использую Qt. Может в нем есть аналоги htonl/ntohl?

3. Копаясь в этих дебрях наткнулся на такой код:
Код

uint64_t htobe64(uint64_t x)
{
    __asm__("bswap %0" : "+r" (x));
    return x;
}

С асмом вообще не дружу, поэтому спрошу: неужели эта одна строчка меняет порядок на BE если он был LE и ничего не делает если он изначально был BE?

Это сообщение отредактировал(а) wowka19 - 6.1.2015, 15:33
PM MAIL   Вверх
baldina
Дата 6.1.2015, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(wowka19 @  6.1.2015,  15:02 Найти цитируемый пост)
ведь они не всегда соразмерно, а это может быть критичным

что не соразмерно?

Цитата(wowka19 @  6.1.2015,  15:02 Найти цитируемый пост)
На самом деле мне не нужно знать какой порядок на машине

на это вам с самого начала намекают. в вики (ссылку я давал раньше) про это тоже есть... для тех кто читает до конца  smile 

Цитата(wowka19 @  6.1.2015,  15:02 Найти цитируемый пост)
Вот только это функции не из стандартной библиотеки

это не стандартная библиотека, но есть на всех платформах (используется для работы с сетью)
http://msdn.microsoft.com/ru-ru/library/wi...6(v=vs.85).aspx
http://linux.die.net/man/3/htonl

PM MAIL   Вверх
fish9370
Дата 7.1.2015, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

Репутация: -1
Всего: 1



Цитата(wowka19 @  6.1.2015,  09:02 Найти цитируемый пост)
1. Как программе самостоятельно определить byte order текущей машины, чтобы потом правильно интерпретировать данные?


в сишном коде в юниксе часто используют примерно такие фокусы:

объявление:
endian.h
Код

#ifndef __BYTE_ORDER
#ifdef __linux__
#include <endian.h>
#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
#if defined(__OpenBSD__)
#include "compat.h"
#endif
#include <machine/endian.h>
#define __BYTE_ORDER BYTE_ORDER
#define __LITTLE_ENDIAN LITTLE_ENDIAN
#define __BIG_ENDIAN BIG_ENDIAN
#else

#ifndef __LITTLE_ENDIAN
#define __LITTLE_ENDIAN         1234
#endif

#ifndef __BIG_ENDIAN
#define __BIG_ENDIAN            4321
#endif

#ifdef __LITTLE_ENDIAN__
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif /* __LITTLE_ENDIAN */

#if defined(sun) && defined(unix) && defined(sparc)
#define __BYTE_ORDER __BIG_ENDIAN
#endif /* sun unix sparc */

#endif /* linux */

#endif /* __BYTE_ORDER */

#ifndef __BYTE_ORDER
#error Need to know endianess
#endif /* __BYTE_ORDER */



compat.h
Код

#ifndef BYTE_ORDER
#define LITTLE_ENDIAN   1234
#define BIG_ENDIAN      4321

#ifdef __sparc__
#define BYTE_ORDER      BIG_ENDIAN
#else
#define BYTE_ORDER      LITTLE_ENDIAN
#endif
#endif

#ifndef __BYTE_ORDER
#define __LITTLE_ENDIAN LITTLE_ENDIAN
#define __BIG_ENDIAN BIG_ENDIAN
#define __BYTE_ORDER BYTE_ORDER
#endif



пример использования:
Код

struct option_header {
        /* Always keep in network byte order */
#if __BYTE_ORDER == __BIG_ENDIAN
        uint16_t flag:3;
        uint16_t option:13;
#else
#if __BYTE_ORDER == __LITTLE_ENDIAN
        uint16_t option:13;
        uint16_t flag:3;
#else
#error Byte order not defined
#endif
#endif
                uint8_t data[0];
};



код из одного известного крупного проекта


Это сообщение отредактировал(а) fish9370 - 7.1.2015, 17:00


--------------------
undefined
PM MAIL WWW ICQ   Вверх
DarthTon
Дата 9.1.2015, 01:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: нет
Всего: 6



Цитата

Какое-то оно чересчур избыточно.
Зачем 4 байта когда и двух хватит?
Зачем такая абсурдная инициализация = 0x01020304, разве просто единицы (= 1) не хватит?
Да и если позанудствовать, то странно видеть в таком коде uint32_t и char[4] вместе, ведь они не всегда соразмерно, а это может быть критичным.

Да, 2 байт действительно хватит, но на скорости исполнения инструкций проверки это не отразится, избыточность тут чисто в коде. uint32_t всегда 4 байта и char всегда 1 байт, это вам не обычный int.
Цитата

на втором месте такой вариант:

Эта штука гораздо более избыточна чем первый вариант... Однако сама htonl конвертирует любой порядок байт в big endian.
Цитата

С асмом вообще не дружу, поэтому спрошу: неужели эта одна строчка меняет порядок на BE если он был LE и ничего не делает если он изначально был BE?

Нет, bswap всегда меняет порядок байт в слове, независимо от исходного порядка.
Цитата

в сишном коде в юниксе часто используют примерно такие фокусы:

Эта штука задает порядок статически, на этапе компиляции. ТСу же надо это определять в рантайме.

Это сообщение отредактировал(а) DarthTon - 9.1.2015, 01:47
PM MAIL   Вверх
wowka19
Дата 13.1.2015, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 30.11.2011

Репутация: нет
Всего: нет



Был уверен, что в Qt есть аналог htonl и нашел его: qToBigEndian().
Но я заглянул в исходник и меня просто поразила реализация.
Код

template <> inline quint32 qbswap<quint32>(quint32 source)
{
    return 0
        | ((source & 0x000000ff) << 24)
        | ((source & 0x0000ff00) << 8)
        | ((source & 0x00ff0000) >> 8)
        | ((source & 0xff000000) >> 24);
}

И она жестко зашита макросом. Т.е. если бинарник запустить на машине с сетевым порядком байт, то все сломается.

Отсюда вопрос: почему проверка не на этапе выполнения? Это чересчур смелое допущение разработчиков Qt? Или на десктопных машинах, на которые рассчитан Qt, просто не выпускают CPU с сетевым порядком байт?

Интересно, в winsock2.h (mingw) функция htonl тоже не выполняет проверку...

Это сообщение отредактировал(а) wowka19 - 13.1.2015, 14:49
PM MAIL   Вверх
baldina
Дата 13.1.2015, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(wowka19 @  13.1.2015,  14:48 Найти цитируемый пост)
почему проверка не на этапе выполнения

потому что порядок байт это свойство процессора. изменить его можно только на процессорах, которые могут по-разному работать (тогда инициализацию порядка байт делает ОС). x86 - это всегда little-endian.
программа, скомпилированная под конкретную платформу, уже имеет заданный порядок.
qbswap(), как видно из названия, просто меняет порядок на обратный.
что касается qToBigEndian(), то её несколько вариантов (по результату условной компиляции), например
Код

#if Q_BYTE_ORDER == Q_BIG_ENDIAN
template <typename T> inline T qToBigEndian(T source)
{ return source; }

см. также http://www.ibm.com/developerworks/ru/library/au-endianc/

PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0774 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.