AlexeyT 0 February 12, 2016 Posted February 12, 2016 (edited) · Report post Задача такая - есть массив 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. Есть идеи, как решить задачу? Edited February 12, 2016 by AlexeyT Quote Share this post Link to post Share on other sites More sharing options...
aaarrr 29 February 12, 2016 Posted February 12, 2016 · Report post __packed unsigned int *tst; Quote Share this post Link to post Share on other sites More sharing options...
Lmx2315 1 February 12, 2016 Posted February 12, 2016 · Report post Есть идеи, как решить задачу? tst = (test_buff[0]<<24) + (test_buff[1]<<16) + (test_buff[2]<<8) + (test_buff[3]<<0); Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 February 12, 2016 Posted February 12, 2016 · Report post При исполнении этого кода на 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)); Quote Share this post Link to post Share on other sites More sharing options...
AlexeyT 0 February 12, 2016 Posted February 12, 2016 · Report post 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) При чем тут арифметическое сложение, вообще непонятно. Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 February 12, 2016 Posted February 12, 2016 · Report post Хм, я думал, что там опечатка в коде. 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-переменной называете указатель? Ну так вас никто не поймёт, выражайтесь корректно. Quote Share this post Link to post Share on other sites More sharing options...
AnatolyT 0 February 12, 2016 Posted February 12, 2016 · Report post Определяем тип: структура с пятью элементами unsigned int. Присваиваем указателю с типом структуры адрес вашего массива. Работаем с элементами структуры. Quote Share this post Link to post Share on other sites More sharing options...
scifi 0 February 12, 2016 Posted February 12, 2016 · Report post Какой-то разговор немого с глухим. Вы можете внятно сформулировать суть проблемы? Потому что в первоначальной формулировке терминологическая путаница и код неточный (не вижу строки, на которой может зависнуть). Quote Share this post Link to post Share on other sites More sharing options...
AlexeyT 0 February 12, 2016 Posted February 12, 2016 (edited) · Report post Нет. Этот код указателю 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); Edited February 12, 2016 by AlexeyT Quote Share this post Link to post Share on other sites More sharing options...
_pv 27 February 12, 2016 Posted February 12, 2016 · Report post ???? 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]; Quote Share this post Link to post Share on other sites More sharing options...
esaulenka 0 February 12, 2016 Posted February 12, 2016 · Report post __packed unsigned int *tst; Самый лаконичный способ, на мой взгляд. Как бы в GCC такое сделать?.. Quote Share this post Link to post Share on other sites More sharing options...
mantech 12 February 12, 2016 Posted February 12, 2016 · Report post Самый лаконичный способ, на мой взгляд. Как бы в GCC такое сделать?.. а чем union не подходит?? Quote Share this post Link to post Share on other sites More sharing options...
aaarrr 29 February 12, 2016 Posted February 12, 2016 · Report post а чем union не подходит?? union не допускает произвольного выравнивания. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 81 February 13, 2016 Posted February 13, 2016 · Report post Самый лаконичный способ, на мой взгляд. Как бы в GCC такое сделать?.. Универсально (компиляторонезависимо): class { unsigned char raw[4]; //здесь добавить перегрузку операторов приведения типа к unsigned и присваивания unsigned }; Quote Share this post Link to post Share on other sites More sharing options...
andrewkrot 0 February 13, 2016 Posted February 13, 2016 · Report post ???? 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) Совсем даже понятно, если не нравится арифметическое сложение, то можете объединить по ИЛИ, и ничего от этого не изменится - результат должен быть одинаковым Quote Share this post Link to post Share on other sites More sharing options...