AlexeyT 0 12 февраля, 2016 Опубликовано 12 февраля, 2016 (изменено) · Жалоба Задача такая - есть массив 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. Есть идеи, как решить задачу? Изменено 12 февраля, 2016 пользователем AlexeyT Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба __packed unsigned int *tst; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lmx2315 5 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба Есть идеи, как решить задачу? tst = (test_buff[0]<<24) + (test_buff[1]<<16) + (test_buff[2]<<8) + (test_buff[3]<<0); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба При исполнении этого кода на 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)); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexeyT 0 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба 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) При чем тут арифметическое сложение, вообще непонятно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба Хм, я думал, что там опечатка в коде. 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-переменной называете указатель? Ну так вас никто не поймёт, выражайтесь корректно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AnatolyT 0 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба Определяем тип: структура с пятью элементами unsigned int. Присваиваем указателю с типом структуры адрес вашего массива. Работаем с элементами структуры. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба Какой-то разговор немого с глухим. Вы можете внятно сформулировать суть проблемы? Потому что в первоначальной формулировке терминологическая путаница и код неточный (не вижу строки, на которой может зависнуть). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexeyT 0 12 февраля, 2016 Опубликовано 12 февраля, 2016 (изменено) · Жалоба Нет. Этот код указателю 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); Изменено 12 февраля, 2016 пользователем AlexeyT Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 78 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба ???? 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]; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба __packed unsigned int *tst; Самый лаконичный способ, на мой взгляд. Как бы в GCC такое сделать?.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 51 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба Самый лаконичный способ, на мой взгляд. Как бы в GCC такое сделать?.. а чем union не подходит?? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 12 февраля, 2016 Опубликовано 12 февраля, 2016 · Жалоба а чем union не подходит?? union не допускает произвольного выравнивания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 13 февраля, 2016 Опубликовано 13 февраля, 2016 · Жалоба Самый лаконичный способ, на мой взгляд. Как бы в GCC такое сделать?.. Универсально (компиляторонезависимо): class { unsigned char raw[4]; //здесь добавить перегрузку операторов приведения типа к unsigned и присваивания unsigned }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewkrot 0 13 февраля, 2016 Опубликовано 13 февраля, 2016 · Жалоба ???? 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) Совсем даже понятно, если не нравится арифметическое сложение, то можете объединить по ИЛИ, и ничего от этого не изменится - результат должен быть одинаковым Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться