Суть проблемы:
Есть некий файл, он заливается в битовый буффер, в файле хранятся данные разных типов
DWORD int CHAR и float. Нужно данные float вытащить из битового буффера отредактировать и
запихнуть обратно.
Здравствуйте, Kven, Вы писали:
K>Есть некий файл, он заливается в битовый буффер, в файле хранятся данные разных типов K>DWORD int CHAR и float. Нужно данные float вытащить из битового буффера отредактировать и K>запихнуть обратно.
Очень просто.
byte b[BUFFER_SIZE];
//b is initialized
//....float *pfNum;
pfNum=(float *)(b+nOffset); //nOffset - offset in byte array of our number
*pfNum=*pfNum+2003;
Здравствуйте, Vamp, Вы писали:
V>Здравствуйте, Kven, Вы писали:
K>>Есть некий файл, он заливается в битовый буффер, в файле хранятся данные разных типов K>>DWORD int CHAR и float. Нужно данные float вытащить из битового буффера отредактировать и K>>запихнуть обратно.
V>Очень просто.
V> V>
V>byte b[BUFFER_SIZE];
V>//b is initialized
V>//....
V>float *pfNum;
V>pfNum=(float *)(b+nOffset); //nOffset - offset in byte array of our number
V>*pfNum=*pfNum+2003;
V>
V>
Так будут проблемы с выравниванием. То есть, если в буфере хранится byte а потом float (nOffset нечётный), то мы получим указатель на float по нечётному адресу.
Так что извлекать нужно так:
Здравствуйте, Vamp, Вы писали:
V>Насколько я понял условия задачи, так вообще ничего не выйдет. А из общих соображений — только reinterpret_cast и не хватает для полного счастья.
А как ты понял условие задачи?
Спрашиваю, так как пользовался таким способом не один раз и все было замечательно.
Кроме того, может хоть каплю конструктива добавишь? Или хотя бы аргументов в пользу своей точки зрения.
Здравствуйте, Артур, Вы писали:
А>Так будут проблемы с выравниванием. То есть, если в буфере хранится byte а потом float (nOffset нечётный), то мы получим указатель на float по нечётному адресу.
Ну и пусть он лежит по нечетному адресу, какая разница? Проблем с выравниванием не будет.
А>memcpy(&a,b+nOffset,sizeof(float));
Здравствуйте, Михаил Можаев, Вы писали:
А>> Так будут проблемы с выравниванием.
ММ> Ну и пусть он лежит по нечетному адресу, какая разница? Проблем с ММ> выравниванием не будет.
Строго говоря, Артур прав. Если, например, для некоей платформы значения float
должны находиться по адресам, кратным, скажем, 4, а в буфере одно из значений
находится по адресу, не соответствующему этому требованию, работа с этим адресом
как с указателем на float, может привести к аппаратному исключению.
С другой стороны, я в значительной степени уверен, что автору вопроса в данном
случае никакого дела до выравнивания нет, т.к., скорее всего, он имеет дело с
Windows on Intel
Posted via RSDN NNTP Server 1.4.6 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
V>> Насколько я понял условия задачи, так вообще ничего не выйдет.
ПК>Можно здесь поподробнее?..
Я так понял, что в битовом массиве лежит много-много всего и где-то не в начале, по определенному смещению находится требуемый флоат. Здесь же никакого смещения.
V>> А из общих соображений — только reinterpret_cast и не хватает для полного счастья.
ПК>А какие альтернативы? Functional cast? — А какая разница?
Любое приведение типов — команда компилятору в стиле "я тут хреново написал, но ты не обращай внимания". Отключается проверка типов компилятора. Приведение указателей — еще туда-сюда, реинтерпрет — совсем плохо, потому что отключает всякие проверки. Поэтому лучше всяческих приведений избегать. И последнее — как я понимаю, реинтерпрет — чисто плюсовая штука. А указатели можно в анси-с приводить.
Здравствуйте, Артур, Вы писали:
А>Так будут проблемы с выравниванием. То есть, если в буфере хранится byte а потом float (nOffset нечётный), то мы получим указатель на float по нечётному адресу.
Вопрос. Как я понимаю, в Intel-архитектуре для увеличения скорости доступа ВСЕ значения имеет смысл выравнивать на размер ЕАХ. Но можно этого и не делать, ничего страшного за исключением падения скорости не произойдет, чему доказательством служит директива pack — можно выравнивать и по единице. Или я где-то неправ?
[]
V>Любое приведение типов — команда компилятору в стиле "я тут хреново написал, но ты не обращай внимания". Отключается проверка типов компилятора. Приведение указателей — еще туда-сюда, реинтерпрет — совсем плохо, потому что отключает всякие проверки. Поэтому лучше всяческих приведений избегать. И последнее — как я понимаю, реинтерпрет — чисто плюсовая штука. А указатели можно в анси-с приводить.
Хм, а чем в данном случае reinterpret_cast<float*>(b) отличается от вашего
(float *)(b+nOffset);
за исключением смещения? Оно что, "всякие проверки" не отключает?
Здравствуйте, Vamp, Вы писали:
V>Здравствуйте, Артур, Вы писали:
А>>Так будут проблемы с выравниванием. То есть, если в буфере хранится byte а потом float (nOffset нечётный), то мы получим указатель на float по нечётному адресу.
V>Вопрос. Как я понимаю, в Intel-архитектуре для увеличения скорости доступа ВСЕ значения имеет смысл выравнивать на размер ЕАХ. Но можно этого и не делать, ничего страшного за исключением падения скорости не произойдет, чему доказательством служит директива pack — можно выравнивать и по единице. Или я где-то неправ?
Здравствуйте, Vamp, Вы писали:
V> Приведение указателей — еще туда-сюда, реинтерпрет - V> совсем плохо, потому что отключает всякие проверки.
То, что ты называешь "приведением указателей", может выполняться
одним из следующих способов: reinterpret_cast, static_cast, const_cast или
их комбинацией. В случае, если написан reinterpret_cast, компилятор слепо
следует инструкциям программиста. В случае "приведения указателей" компилятор
подбирает одну из работающих комбинаций, оставляя не больше проверок, нежели
с reinterpret_cast (на деле даже меньше). В данном случае "приведение указателей"
будет выполняться именно через reinterpret_cast, только в коде будет выглядеть
чуть безобиднее. Таким образом, из всех "опасных" приведений типов то,
что ты назвал "приведением указателей" — самое опасное.
V> реинтерпрет — чисто плюсовая штука. А указатели можно в анси-с приводить.
Это — да, аргумент
Posted via RSDN NNTP Server 1.4.6 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
ПК>То, что ты называешь "приведением указателей", может выполняться ПК>одним из следующих способов: reinterpret_cast, static_cast, const_cast или ПК>их комбинацией.
Если ты в этом уверен, значит так оно и есть. Хоть на С, хоть на С++ — только cast-семейство. Я все равно, конечно, не понимаю — что значит "может выполняться" с точки зрения компилятора. Я считал, что приведение типов проосто сообщает компилятору, что данное присваивание корректно и вообще ничего не выполняет (случаи с переопределениями приведения типов а-ля CString рассматривать не будем), но значит, я жестоко ошибался.
ДН>>А кто сказал, что здесь про Intel говорят?
V>А про что тогда тут говорят? А то как-то неконкретно.
Был задан вопрос:
Суть проблемы:
Есть некий файл, он заливается в битовый буффер, в файле хранятся данные разных типов
DWORD int CHAR и float. Нужно данные float вытащить из битового буффера отредактировать и
запихнуть обратно.
Упоминания про конкретную платформу не было. Поэтому, как сказал Миша Можаев:
Только что, за чашкой чая, пришли к этому же
мы обсуждали ситуацию, про которую сказал Павел Кузнецов:
Строго говоря, Артур прав. Если, например, для некоей платформы значения float
должны находиться по адресам, кратным, скажем, 4, а в буфере одно из значений
находится по адресу, не соответствующему этому требованию, работа с этим адресом
как с указателем на float, может привести к аппаратному исключению.
Конечно можно сказать — "в моем случае все и так работает, и я не хочу делать лишних телодвижений". Только потом наступает момент, когда вы вынуждены перенести свой код (который, как вам кажется, полностью ANSI С compliant) на другую платформу и с удивлением обнаружить большие проблемы с выравниванием, познакомиться с двумя индейцами — Big & Little и со множеством других проблем.
Здравствуйте, Дмитрий Наумов, Вы писали: ДН>мы обсуждали ситуацию, про которую сказал Павел Кузнецов: ДН>
ДН>Строго говоря, Артур прав. Если, например, для некоей платформы значения float
ДН>должны находиться по адресам, кратным, скажем, 4, а в буфере одно из значений
ДН>находится по адресу, не соответствующему этому требованию, работа с этим адресом
ДН>как с указателем на float, может привести к аппаратному исключению.
Вопрос только в том, для какой. Существуют ли платформы, на которых флоаты должны распологаться по четным адресам? Потому, что если таких платформ никто назвать не может, то спор беспредметен.
ДН>познакомиться с двумя индейцами — Big & Little и со множеством других проблем.
Те будут не индейцы, а оконечники Свифтовские — тупые и острые. Но это к делу не относится.
Здравствуйте, Vamp, Вы писали:
V> Если ты в этом уверен, значит так оно и есть.
Вовсе не обязательно верить мне на слово ты волен прочитать стандарт самостоятельно (пункты 5.2.3, 5.2.7, 5.2.9, 5.2.10, 5.2.11, 5.4).
V> Хоть на С, хоть на С++ — только cast-семейство.
Естественно, речь шла о C++. В C присутствует только C-style cast. В C++ последний, как уже было сказано, является самой опасной формой преобразований типов.
V> Я все равно, конечно, не понимаю — что значит V> "может выполняться" с точки зрения компилятора.
"Выполняться" — мой вольный перевод слова "perform", употребляющегося в стандарте C++.
Posted via RSDN NNTP Server 1.4.6 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен