Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
prosto_lynx
49 / 24 / 1
Регистрация: 09.06.2008
Сообщений: 226
#1

Как массив char[4] перевести в unsigned int? - C++

06.04.2012, 21:33. Просмотров 2712. Ответов 54
Метки нет (Все метки)

Есть массив из 4х char символов (4-е байта), нужно его перевести в unsigned int.
Я сделал втупую:
C++
1
2
3
4
5
6
7
        unsigned int B=0;
        long Ex = 256 * 256 * 256;
        for (int i=0; i<4; i++)
        {
                B8 += t[i] * Ex;
                Ex /= 256;
         }
Можно ли это как-то упростить?.. а то уж слишком некрасиво, долго и программу засоряет...

Я мыслю так, т.к. обе переменные (и 4-е char'a, и int) 4-х байтовые, то появилось предположение, что можно, как-нибудь, например, обратиться к char-массиву, сразу записав его в переменную int не преобразовывая?..
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.04.2012, 21:33     Как массив char[4] перевести в unsigned int?
Посмотрите здесь:

Доступны ли побитовые операции с unsigned char типом (одно-байтовой переменной) без неявного приведения к INT - C++
Отказавшись от bitset мне удалось ускорить работу программы примерно в 2,25 раза Вот её код (ребят cyberforum.ru - не сохраняет оригинал...

Перевести char* в int - C++
Всем привет. Такая проблема: есть указатель на char, допустим char*time = &quot;20&quot;; и есть число, допустим int k = 23; Вопрос - как перевести...

Создать массив объединений, содержащих поля unsigned int и float - C++
Очень вас прошу! Нужно написать на С++ программу! Я уже отчаялась. Часа 2 над этим сижу В программе должно быть как минимум 2...

Порядок байт. Массив чаров приводится к типу unsigned int. - C++
Есть массив из 4 char. Массив приводится к типу unsigned int и затем данные извлекаются в переменную типа unsigned int. Нужно, чтобы байты...

Не могу вывести unsigned char символ. Как исправить? - C++
Данна задача, при помощи массива сформировать структуру лабиринта, где в качестве стен используется символ 177, а в качестве прохода...

Как задать границу для типа данных unsigned char*? - C++
У меня есть двумерный массив значений типа unsigned char*, диапазон значений которого 0 - 255. Как задать условие, чтобы при увеличении на...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Sergey-K
233 / 224 / 13
Регистрация: 27.10.2011
Сообщений: 249
06.04.2012, 21:52     Как массив char[4] перевести в unsigned int? #2
Сообщение было отмечено автором темы, экспертом или модератором как ответ
C++
1
2
char ch[4] = {'a', 'b', 'c', 'd'};
int i = *(int *)ch;
George22
12 / 10 / 1
Регистрация: 04.04.2012
Сообщений: 29
07.04.2012, 10:26     Как массив char[4] перевести в unsigned int? #3
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Sergey-K красиво!

C++
1
2
3
4
5
 char t[4] ={0x04,0x03,0x02,0x01};
 int ex=0;
 
 for(int i=0;i<4;i++)
 ex+=(int)t[i]<<(i<<3);
Добавлено через 12 часов 30 минут
И еще:
C++
1
2
3
4
5
union
{
char t[4];
int i;
} number = {'a','b','c','d'};
Evg
Эксперт CАвтор FAQ
17547 / 5785 / 370
Регистрация: 30.03.2009
Сообщений: 15,934
Записей в блоге: 26
07.04.2012, 12:56     Как массив char[4] перевести в unsigned int? #4
При этом надо понимать, что код из поста 2 и код с union'ом из поста 3 будут работать только на little-endian машинах. Код из поста 2 надёжно будет работать только на машинах, в которых разрешены невыровненные обращения в память. Intel'овские процессоры удовлетворяют обоим критериям, а потому для "домашнего" использования или для программы, которая будет работать исключительно на Intel'е это канает, но в общем случае - нет
prosto_lynx
49 / 24 / 1
Регистрация: 09.06.2008
Сообщений: 226
09.04.2012, 11:52  [ТС]     Как массив char[4] перевести в unsigned int? #5
Цитата Сообщение от Evg Посмотреть сообщение
При этом надо понимать, что код из поста 2 и код с union'ом из поста 3 будут работать только на little-endian машинах. Код из поста 2 надёжно будет работать только на машинах, в которых разрешены невыровненные обращения в память. Intel'овские процессоры удовлетворяют обоим критериям, а потому для "домашнего" использования или для программы, которая будет работать исключительно на Intel'е это канает, но в общем случае - нет
Спасибо, для меня этот вопрос важен.
Я так понял, что little-endian используется не только на интеловских процессорах, а вообще на архитектуре 86?
p.s. Тогда, правильно ли я понимаю, что код из поста 2 всегда будет работать, если прога запущена из-под XP? (Запуск эмулятора XP я не рассматриваю).
Evg
Эксперт CАвтор FAQ
17547 / 5785 / 370
Регистрация: 30.03.2009
Сообщений: 15,934
Записей в блоге: 26
09.04.2012, 12:40     Как массив char[4] перевести в unsigned int? #6
Цитата Сообщение от prosto_lynx Посмотреть сообщение
Я так понял, что little-endian используется не только на интеловских процессорах, а вообще на архитектуре 86?
Словом "Intel" я называл архитектуру процессора. Т.е. это все процессоры x86, x64_64, не важно кем произведённые (Intel'ом, AMD, может кто-то ещё выпускает)

Цитата Сообщение от prosto_lynx Посмотреть сообщение
p.s. Тогда, правильно ли я понимаю, что код из поста 2 всегда будет работать, если прога запущена из-под XP? (Запуск эмулятора XP я не рассматриваю).
Да. Причём независимо от того, реальная это машина или эмулятор.
bugaboo
3 / 3 / 0
Регистрация: 12.06.2017
Сообщений: 37
12.06.2017, 10:39     Как массив char[4] перевести в unsigned int? #7
А можно расшифровку способа №1 в 3 посте? его эффективность зависит от процессора?

Добавлено через 3 часа 33 минуты
По зрелом размышлении удалось на основе поста №3 сделать вот такую функцию
C++
1
2
3
4
5
6
7
8
9
unsigned int uintof4b(char buffer[4])
{
    unsigned int x = 0;
    for (int i = 0; i < 4; i++)
    {
        x += (unsigned char)buffer[3 - i] << (i << 3);
    }
    return x;
}
работает с учетом того, что могут встретиться отрицательные charы и возвращает беззнаковый результат. Странно, что для такой простой задачи приходится изобретать такой сложный костыль
Evg
Эксперт CАвтор FAQ
17547 / 5785 / 370
Регистрация: 30.03.2009
Сообщений: 15,934
Записей в блоге: 26
12.06.2017, 16:19     Как массив char[4] перевести в unsigned int? #8
Цитата Сообщение от bugaboo Посмотреть сообщение
Странно, что для такой простой задачи приходится изобретать такой сложный костыль
Просто и без изобретения костылей - это использовать memcpy. Подозреваю, что большинство компиляторов сумеют это дело соптимизировать и привести код к тому же состоянию, что и в "сложных" вариантах. Правда, так же как и в других предоставленных вариантах, код получится правильно работающим только на little-endian
TRam_
139 / 139 / 39
Регистрация: 14.05.2017
Сообщений: 537
12.06.2017, 16:39     Как массив char[4] перевести в unsigned int? #9
bugaboo, более правильным подходом был бы
C++
1
2
3
4
5
6
7
8
9
unsigned int uintof4b(char buffer[4])
{
    unsigned int x = 0;
    for (int i = 0; i < 4; i++)
    {
        x |= static_cast<unsigned int>(buffer[3 - i]) << (i * 8);
    }
    return x;
}
хотя не некоторых процессорах (i << 3) работает быстрее чем (i * 8).

Если использовать побитовое "или" вместо "+", то преобразование signed/unsigned теряет смысл. Правда так можно только для данного случая (собираемые байты друг с другом не пересекаются), иначе будет ошибка.

И по логике, если б небыло неяного преобразования из char в int, то в результате операции
C++
1
(unsigned char)buffer[3 - i] << (i << 3)
был бы 0 (при i > 0), т.к. в char всего один байт, и если его смещать, то не вошедшая в этот байт часть пропадёт.

Добавлено через 4 минуты
А стандартный вариант - это всё же использование memcpy -
C++
1
memcpy(&x, buffer, sizeof(int));
Evg
Эксперт CАвтор FAQ
17547 / 5785 / 370
Регистрация: 30.03.2009
Сообщений: 15,934
Записей в блоге: 26
12.06.2017, 16:49     Как массив char[4] перевести в unsigned int? #10
Цитата Сообщение от TRam_ Посмотреть сообщение
хотя не некоторых процессорах (i << 3) работает быстрее чем (i * 8)
Я бы сказал, что не "на некоторых", а "скорее всего поголовно на всех"

Цитата Сообщение от TRam_ Посмотреть сообщение
Если использовать побитовое "или" вместо "+", то преобразование signed/unsigned теряет смысл
На коротком примере моделируются два случая: один с преобразованием в unsigned, другой без. Как видишь, разница есть. А потому преобразование в unsigned нельзя удалять независимо от того, через or делается сборка результата, или через plus

C
#include <stdio.h>
 
int main (void)
{
  unsigned int x;
  char buffer1 = 255;
 
  x = 0xaa000000;
  x |= (buffer1 << 8);
  printf ("%x\n", x);
 
  x = 0xaa000000;
  x |= ((unsigned char)buffer1 << 8);
  printf ("%x\n", x);
}
Код
$ gcc t.c
$ ./a.out
ffffff00
aa00ff00
TRam_
139 / 139 / 39
Регистрация: 14.05.2017
Сообщений: 537
12.06.2017, 17:39     Как массив char[4] перевести в unsigned int? #11
Evg, спасибо! Действительно неверно представлял себе поведение знаковых чисел при их преобразовании к типу с большим числом байтов. Так что или
C++
1
static_cast<unsigned char>(buffer[3 - i])
или
C++
1
(buffer[3 - i] & 0x000000FF)
bugaboo
3 / 3 / 0
Регистрация: 12.06.2017
Сообщений: 37
12.06.2017, 20:21     Как массив char[4] перевести в unsigned int? #12
Evg, я новичок и поэтому могу говорить только на уровне "у меня работает/не работает". Но хотелось бы, чтобы потом оно работало независимо от способа представления данных процессором. Суть у меня в том, что я читаю эти 4 charа из файла MIDI(функцией read), в котором всегда используется big-endian, и они из себя представляют беззнаковый int. Любой из этих байтов может запросто прочитаться как отрицательный (хотя в большинстве случаев таким не является, а является беззнаковым). Есть ли какой-то универсальный способ прочтения 4х байт в int из файла, чтобы результат преобразования был правильным, независимо от того, big-endian или little-endian схема используется в процессоре?
Я же не в космос улетаю, мне всего то надо 4 байта прочитать - откуда берутся такие сложности?
TRam_
139 / 139 / 39
Регистрация: 14.05.2017
Сообщений: 537
12.06.2017, 21:33     Как массив char[4] перевести в unsigned int? #13
bugaboo, сложность в том, что тут
1) идёт преобразование из одного байта в 4. То есть char был 1, а тут ещё три новых добавилось. Если использовать знаковый тип, то все биты новых байтов заполнятся 1цами в случае, если первый бит у него 1ца. Это в любом случае, что для big-endian, что для little-endian. Для большей производительности лучше сделать преобразование в unsigned типа указателя:
C++
1
unsigned char *uns_buffer = reinterpret_cast<unsigned char *>buffer;
2) порядок байтов, то есть, в одних архитектурах процессоров для счёта самыми старшими разрядами считаются первые байты (и далее последующие), а где-то наоборот. То есть в одном будет "0хFA6C9001", а в другом то же число - "0x01906CFA". Соответственно если в стандарте MIDI указан Big Endian, то чтоб производить арифметические операции с этим числом на процессорах x86, тебе нужно переворачивать байты, а если будешь писать например для архитектуры ARM, то переворачивать не нужно и достаточно простого memcpy()
Evg
Эксперт CАвтор FAQ
17547 / 5785 / 370
Регистрация: 30.03.2009
Сообщений: 15,934
Записей в блоге: 26
12.06.2017, 22:06     Как массив char[4] перевести в unsigned int? #14
Цитата Сообщение от bugaboo Посмотреть сообщение
Есть ли какой-то универсальный способ прочтения 4х байт в int из файла, чтобы результат преобразования был правильным, независимо от того, big-endian или little-endian схема используется в процессоре?
В варианте с файлом есть как бы два endian'а: endian машины, на которой запущена программа и endian, в котором записаны данные в файле. Нужно просто взять и считать эти 4 байта в целочисленную переменную 4-байтного размера. В случае совпадения endian'ов машины и файла больше ничего делать не надо. Если endian'ы различаются, то байты в числе надо развернуть задом наперёд

Или, что тоже самое. Взять твой вариант из поста #7 и в зависимости от совпадающих или различающихся endian'ов прочитать байты в прямом или обратном порядке. Тут надо немного думать и экспериментировать, если честно, мне уже лениво под вечер

Какой endian у машины, на которой происходит запуск, можно проверить в runtime:

C
unsigned int x = 0x11223344;
char *p = (char*) &x;
if (*p == 0x44)
  little endian;
else
  big endian;
Добавлено через 8 минут
Цитата Сообщение от bugaboo Посмотреть сообщение
Любой из этих байтов может запросто прочитаться как отрицательный (хотя в большинстве случаев таким не является, а является беззнаковым)
К слову говоря, байт не бывает положительным или отрицательным. Байт - это всего лишь набор битов. А "положительный" и "отрицательный" - это всего лишь трактовки. Для самообразования можешь почитать:

Signed/Unsigned
Signed/Unsigned
Signed/Unsigned
Тип char.Signed/unsigned.Отличие типов данных.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.06.2017, 02:13     Как массив char[4] перевести в unsigned int?
Еще ссылки по теме:

Массив int перевести в буфер - C++
Нужно перевести массив интов в char* array, а потом это сделать наоборот т.е опять получить массив интов. Добавлено через 1 минуту ...

Перевести массив цифр в число типа int или float - C++
Всем здрасти , а не подскажет ли кто часом, можно ли массив с цифрой в каждом злементе (a=1, a=3, a=7, a=n и.т.д) перевести в число типа...

Контейнер для unsigned char * - C++
возьмем например char * для него в с++ есть стандартный контейнер и называется он std::string возьмем например Delphi там...

Почему плохо использовать unsigned int? - C++
Почему плохо использовать unsigned int и чему он удобней для представления массивов бит чеm signed int? (Из Страуструпа)


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
bugaboo
3 / 3 / 0
Регистрация: 12.06.2017
Сообщений: 37
14.06.2017, 02:13     Как массив char[4] перевести в unsigned int? #15
Evg, тогда, наверно, такой вариант будет универсальным?
C++
1
2
3
4
5
6
        unsigned char buf[4];
        unsigned int x = 0;
        for (int i = 0; i < 4; i++)
            buf[i] = ifs.get();
        for (int i = 0; i < 4; i++)
            x += buf[3 - i] << (i << 3);
байты считываются заведомо как положительные числа в определенном порядке(файл заведомо big-endian, открыт как бинарный), а х вычисляется как сумма, то есть его представление в памяти не важно. У меня работает ))
Yandex
Объявления
14.06.2017, 02:13     Как массив char[4] перевести в unsigned int?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru