Перейти к содержанию
    

Формирование int из массива char

Задача такая - есть массив test_buff, из подряд идущих 4-х элементов которого нужно сформировать переменную unsigned int.

 

unsigned char test_buff[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};

unsigned char *tst_point = &test_buff[0];

unsigned int *tst;

 

tst = (unsigned int *)(tst_point + 2*sizeof(unsigned char)); //должны получить 0x06050403 = 100992003

 

Т.е. в *tst пытаюсь записать unsigned int, состоящий из байтов массива с 3-го по 6-й.

 

При исполнении этого кода на ARM-процессоре (ядро Cortex-M1) происходит зависание ядра (когда обращаюсь к адресу, некратному 4 байтам).

При исполнении этого же кода на ПК - все ок, *tst = 100992003, как и должно быть.

Компилятор Keil.

 

Есть идеи, как решить задачу?

Изменено пользователем AlexeyT

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть идеи, как решить задачу?

 

tst = (test_buff[0]<<24) + (test_buff[1]<<16) + (test_buff[2]<<8) + (test_buff[3]<<0);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При исполнении этого кода на ARM-процессоре (ядро Cortex-M1) происходит зависание ядра (когда обращаюсь к адресу, некратному 4 байтам).

Ну естественно, Cortex-M1 не умеет делать доступ по неровным адресам.

 

При исполнении этого же кода на ПК - все ок, *tst = 100992003, как и должно быть.

Почему должно? Кто сказал? Просто x86 умеет делать доступ по неровным адресам. Скажем, даже взрослый SPARC из старенького сервера Sun не умеет.

 

Используйте memcpy:

unsigned char test_buff[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
unsigned int tst;
memcpy(&tst, test_buff + 2, sizeof(tst));

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

tst = (test_buff[0]<<24) + (test_buff[1]<<16) + (test_buff[2]<<8) + (test_buff[3]<<0);

 

????

 

1) Мне нужна int-переменная, состоящая из test_buff[2]...test_buff[5].

2) test_buff[0]<<24 даст все нули, т.к. имеет 8 бит.

3) При чем тут арифметическое сложение, вообще непонятно.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хм, я думал, что там опечатка в коде.

unsigned int *tst;

 

tst = (unsigned int *)(tst_point + 2*sizeof(unsigned char)); //должны получить 0x06050403 = 100992003

 

Т.е. в *tst пытаюсь записать unsigned int, состоящий из байтов массива с 3-го по 6-й.

Нет. Этот код указателю tst присваевается адрес элемента другого массива &test_buff[2].

 

При исполнении этого кода на ARM-процессоре (ядро Cortex-M1) происходит зависание ядра (когда обращаюсь к адресу, некратному 4 байтам).

При исполнении какой конкретно строки кода происходит зависание?

 

1) Мне нужна int-переменная, состоящая из test_buff[2]...test_buff[5].

Это именно то, что я сделал в этом коде. Или вы int-переменной называете указатель? Ну так вас никто не поймёт, выражайтесь корректно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Определяем тип: структура с пятью элементами unsigned int.

Присваиваем указателю с типом структуры адрес вашего массива.

Работаем с элементами структуры.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какой-то разговор немого с глухим. Вы можете внятно сформулировать суть проблемы? Потому что в первоначальной формулировке терминологическая путаница и код неточный (не вижу строки, на которой может зависнуть).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет. Этот код указателю tst присваевается адрес элемента другого массива &test_buff[2].

 

Само собой, указателю tst присваивается адрес массива test_buff[2].

При этом значение int-переменной я получаю, обратившись к *tst.

 

В каком именно месте происходит зависание, сказать не могу, процессор - 1986ВЕ1Т, там с дебагом туго.

 

Вот полный исходник тестового кода, на котором все виснет:

 

unsigned char test_buff[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};

unsigned char *tst_point = &test_buff[0];

unsigned int *tst;

unsigned int temp;

 

tst = (unsigned int *)(tst_point + 2*sizeof(unsigned char)); //должны получить 0x06050403 = 100992003

 

temp = *tst;

 

printf("%d", temp);

 

Изменено пользователем AlexeyT

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

????

 

1) Мне нужна int-переменная, состоящая из test_buff[2]...test_buff[5].

2) test_buff[0]<<24 даст все нули, т.к. имеет 8 бит.

3) При чем тут арифметическое сложение, вообще непонятно.

 

нельзя обращаться к 32х разрядным данным по невыровненным адресам (не кратным 4).

копируйте побайтно либо руками, как сказал Lmx2315, либо через memcpy.

 

3) что "+" что "|" тут без разницы.

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

 

int temp;

((unsigned char *)(&temp))[0] = test_buff[2];

((unsigned char *)(&temp))[1] = test_buff[3];

((unsigned char *)(&temp))[2] = test_buff[4];

((unsigned char *)(&temp))[3] = test_buff[5];

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

__packed unsigned int *tst;

Самый лаконичный способ, на мой взгляд.

Как бы в GCC такое сделать?..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Самый лаконичный способ, на мой взгляд.

Как бы в GCC такое сделать?..

 

а чем union не подходит??

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Самый лаконичный способ, на мой взгляд.

Как бы в GCC такое сделать?..

Универсально (компиляторонезависимо):

class {

unsigned char raw[4];

//здесь добавить перегрузку операторов приведения типа к unsigned и присваивания unsigned

};

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

????

 

1) Мне нужна int-переменная, состоящая из test_buff[2]...test_buff[5].

2) test_buff[0]<<24 даст все нули, т.к. имеет 8 бит.

3) При чем тут арифметическое сложение, вообще непонятно.

1) Ну так вместо 0,1,2,3 в индексах поставьте 2,3,4,5

2) Не даст все нули, т.к. сдвинется в переменную типа int, и станет там самым старшим байтом

3) Совсем даже понятно, если не нравится арифметическое сложение, то можете объединить по ИЛИ, и ничего от этого не изменится - результат должен быть одинаковым

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...