Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Int из масива байт.


Автор: klein 29.3.2011, 17:30
Привет.
Есть масив из 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;


Спасибо

Автор: KaraKum 29.3.2011, 17:40
Хех, с удивительным везением все 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 

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

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

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

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

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

А что значит "не работает"? Что в итоге получается?

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

не пройдет.

проблема переносимости #2
Вышеупомянутый http://en.wikipedia.org/wiki/Endianness. Работать будет не на всех платформах.

проблема переносимости #3
Так вообще делать нельзя, по причине проблемы выравнивания на некоторых системах.

Автор: xvr 30.3.2011, 11:28
Цитата(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, может не работать

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

Эмм, немного не понял.
Под нулевым индексом в массиве buf находится старший байт, а в следующем индексе (по ходу увеличения адреса памяти) находится младший. Посредством (buf[0] << 8) | buf[1] получается проецирование этой области памяти в два байта из buf в result?
 smile 

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

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


Автор: KaraKum 30.3.2011, 18:55
Да. Я перепутал.  smile 

Автор: klein 1.4.2011, 13:24
Всем спасибо, оч помогли.

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


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-х


Автор: KaraKum 1.4.2011, 13:39
Цитата(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 порядком, что сегодня довольно-таки редко. Какой компьютер?

Автор: klein 1.4.2011, 16:17
Виртуальная машина Parallels Desktop. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)