|
|
  |
Формирование int из массива char |
|
|
|
Feb 12 2016, 15:05
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 5-06-07
Пользователь №: 28 207

|
Задача такая - есть массив 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 - Feb 12 2016, 15:07
|
|
|
|
|
Feb 12 2016, 15:14
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(AlexeyT @ Feb 12 2016, 18:05)  При исполнении этого кода на ARM-процессоре (ядро Cortex-M1) происходит зависание ядра (когда обращаюсь к адресу, некратному 4 байтам). Ну естественно, Cortex-M1 не умеет делать доступ по неровным адресам. Цитата(AlexeyT @ Feb 12 2016, 18:05)  При исполнении этого же кода на ПК - все ок, *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));
|
|
|
|
|
Feb 12 2016, 15:18
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 5-06-07
Пользователь №: 28 207

|
Цитата(Lmx2315 @ Feb 12 2016, 18:10)  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) При чем тут арифметическое сложение, вообще непонятно.
|
|
|
|
|
Feb 12 2016, 15:27
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Хм, я думал, что там опечатка в коде. Цитата(AlexeyT @ Feb 12 2016, 18:05)  unsigned int *tst;
tst = (unsigned int *)(tst_point + 2*sizeof(unsigned char)); //должны получить 0x06050403 = 100992003
Т.е. в *tst пытаюсь записать unsigned int, состоящий из байтов массива с 3-го по 6-й. Нет. Этот код указателю tst присваевается адрес элемента другого массива &test_buff[2]. Цитата(AlexeyT @ Feb 12 2016, 18:05)  При исполнении этого кода на ARM-процессоре (ядро Cortex-M1) происходит зависание ядра (когда обращаюсь к адресу, некратному 4 байтам). При исполнении какой конкретно строки кода происходит зависание? Цитата(AlexeyT @ Feb 12 2016, 18:18)  1) Мне нужна int-переменная, состоящая из test_buff[2]...test_buff[5]. Это именно то, что я сделал в этом коде. Или вы int-переменной называете указатель? Ну так вас никто не поймёт, выражайтесь корректно.
|
|
|
|
|
Feb 12 2016, 15:32
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 5-06-07
Пользователь №: 28 207

|
Цитата(scifi @ Feb 12 2016, 18:27)  Нет. Этот код указателю 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 - Feb 12 2016, 15:35
|
|
|
|
|
Feb 12 2016, 15:48
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
Цитата(AlexeyT @ Feb 12 2016, 21:18)  ????
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];
|
|
|
|
|
Feb 13 2016, 06:18
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(esaulenka @ Feb 12 2016, 22:02)  Самый лаконичный способ, на мой взгляд. Как бы в GCC такое сделать?.. Универсально (компиляторонезависимо): class { unsigned char raw[4]; //здесь добавить перегрузку операторов приведения типа к unsigned и присваивания unsigned };
|
|
|
|
|
Feb 13 2016, 19:03
|
Местный
  
Группа: Участник
Сообщений: 306
Регистрация: 11-11-04
Из: Москва
Пользователь №: 1 106

|
Цитата(AlexeyT @ Feb 12 2016, 19:18)  ????
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) Совсем даже понятно, если не нравится арифметическое сложение, то можете объединить по ИЛИ, и ничего от этого не изменится - результат должен быть одинаковым
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|