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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Int из масива байт. 
V
    Опции темы
klein
Дата 29.3.2011, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Привет.
Есть масив из 2 байт (char). Хочу преобразовать в int. Масив читаю с файла, получаемые результаты упорно не совпадают с показаниями хекс редактора. Компилятор - visual studio 2010.
Код

        int result = 0;
    char buf[2];

    result = *(int *)buf; // не помогло

    result =  (buf[1]<<8)|(buf[0] << 8);  // не помогло
    
    memcpy(&result, &buf, sizeof(char)); // не помогло

    return result;


Спасибо
PM MAIL   Вверх
KaraKum
Дата 29.3.2011, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Хех, с удивительным везением все 3 метода использованы немного неверно  smile 

Код

result = *(int *)buf;

Читается 4 байта, а в исходном массиве всего два - этот метод вообще не подойдёт.



Код

result =  (buf[1]<<8)|(buf[0] << 8);

Вот так должно отработать:
Код

result =  (buf[0] << 8) | buf[1];

При условии что порядок байт в "little endian" (что почти наверняка).



Код

memcpy(&result, &buf, sizeof(char));

Копируется только один байт, нужно 2 и не в адрес указателя на массив, а в сам массив:
Код

result = 0;
memcpy(&result + 2, buf, sizeof(char) * 2);



 smile 

Это сообщение отредактировал(а) KaraKum - 29.3.2011, 17:43
PM MAIL WWW   Вверх
klein
Дата 29.3.2011, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



KaraKum 
Спасибо за оперативную помощь. Второй метод не работает. 
А третий -
Код

result = 0;
memcpy(&result + 2, buf, sizeof(char) * 2);

 выдает 0. Немогу понять почему &result + 2 ? 

Это сообщение отредактировал(а) klein - 29.3.2011, 18:00
PM MAIL   Вверх
KaraKum
Дата 29.3.2011, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Данные в памяти в случае с "little endian" располагаются от старшего байта к младшему при увеличении адреса. То в есть response нужно скопировать два байта в конец, а указатель на него указывает на первый его байт, поэтому и прибавляем два.
Странно что второй метод не работает - нужно тогда попробовать явно преобразовывать к  (int):
Код

result =  0x00000000 | (int)(buf[0] << 8) | (int)buf[1];

А что значит "не работает"? Что в итоге получается?
PM MAIL WWW   Вверх
azesmcar
Дата 29.3.2011, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



проблема переносимости #1
int практически на всех платформах имеет размер 4 байта, так что
Цитата(klein @  29.3.2011,  17:30 Найти цитируемый пост)
Есть масив из 2 байт (char). Хочу преобразовать в int

не пройдет.

проблема переносимости #2
Вышеупомянутый endianness. Работать будет не на всех платформах.

проблема переносимости #3
Так вообще делать нельзя, по причине проблемы выравнивания на некоторых системах.
PM   Вверх
xvr
Дата 30.3.2011, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(KaraKum @  29.3.2011,  17:40 Найти цитируемый пост)
Вот так должно отработать:
Код

result =  (buf[0] << 8) | buf[1];


При условии что порядок байт в "little endian" (что почти наверняка).

Для "little endian" должно быть наоборот -
Код

result =  (buf[1] << 8) | buf[0];
или просто
Код

result =  *(unsigned short*)buf;

PS. Последний вариант на платформе с требованием к выравниванию более строгими, чем у x86, может не работать

PM MAIL   Вверх
KaraKum
Дата 30.3.2011, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(xvr @  30.3.2011,  12:28 Найти цитируемый пост)
Для "little endian" должно быть наоборот -

Эмм, немного не понял.
Под нулевым индексом в массиве buf находится старший байт, а в следующем индексе (по ходу увеличения адреса памяти) находится младший. Посредством (buf[0] << 8) | buf[1] получается проецирование этой области памяти в два байта из buf в result?
 smile 
PM MAIL WWW   Вверх
xvr
Дата 30.3.2011, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(KaraKum @  30.3.2011,  11:50 Найти цитируемый пост)
Под нулевым индексом в массиве buf находится старший байт, а в следующем индексе (по ходу увеличения адреса памяти) находится младший.
Это как раз Big Endian. При little endian младший байт находится по младшему адресу в памяти.
Код

01 02 -> 0201 (Little Endian)
01 02 -> 0102 (Big Endian)


PM MAIL   Вверх
KaraKum
Дата 30.3.2011, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Да. Я перепутал.  smile 
PM MAIL WWW   Вверх
klein
Дата 1.4.2011, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Всем спасибо, оч помогли.

Может кому понадобитса: 
Код


byte = str[0]; //из одного байта

word = (int)(str[1]) | (int)(str[0]<<8); // 2-х

dword = (int)str[0]<<24 | (int)(str[1]<<16)|(int)(str[2]<<8)|(int)(str[3]); // 3-х


PM MAIL   Вверх
KaraKum
Дата 1.4.2011, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(klein @  1.4.2011,  14:24 Найти цитируемый пост)
word = (int)(str[1]) | (int)(str[0]<<8); // 2-х

Эмм, так разве работает?
xvr же дал мне подзатыльник по поводу того что я перепутал little endian с big endian. После чего, теоретически, стало ясно что на little endian должен работать вариант
Код

result =  (buf[1] << 8) | buf[0];

или, что тоже самое:
Код

result =  buf[0] | (buf[1] << 8);

то есть наоборот по сравнению с приведённым якобы работающим результатом.
Видимо это проверялось на компьютере с big endian порядком, что сегодня довольно-таки редко. Какой компьютер?
PM MAIL WWW   Вверх
klein
Дата 1.4.2011, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Виртуальная машина Parallels Desktop. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.6629 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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