Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Формирование int из массива char
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
AlexeyT
Задача такая - есть массив 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.

Есть идеи, как решить задачу?
aaarrr
__packed unsigned int *tst;
Lmx2315
Цитата(AlexeyT @ Feb 12 2016, 18:05) *
Есть идеи, как решить задачу?


tst = (test_buff[0]<<24) + (test_buff[1]<<16) + (test_buff[2]<<8) + (test_buff[3]<<0);
scifi
Цитата(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));
AlexeyT
Цитата(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) При чем тут арифметическое сложение, вообще непонятно.

scifi
Хм, я думал, что там опечатка в коде.
Цитата(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-переменной называете указатель? Ну так вас никто не поймёт, выражайтесь корректно.
AnatolyT
Определяем тип: структура с пятью элементами unsigned int.
Присваиваем указателю с типом структуры адрес вашего массива.
Работаем с элементами структуры.
scifi
Какой-то разговор немого с глухим. Вы можете внятно сформулировать суть проблемы? Потому что в первоначальной формулировке терминологическая путаница и код неточный (не вижу строки, на которой может зависнуть).
AlexeyT
Цитата(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);
_pv
Цитата(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];
esaulenka
Цитата(aaarrr @ Feb 12 2016, 18:10) *
__packed unsigned int *tst;

Самый лаконичный способ, на мой взгляд.
Как бы в GCC такое сделать?..
mantech
Цитата(esaulenka @ Feb 12 2016, 19:02) *
Самый лаконичный способ, на мой взгляд.
Как бы в GCC такое сделать?..


а чем union не подходит??
aaarrr
Цитата(mantech @ Feb 12 2016, 23:29) *
а чем union не подходит??

union не допускает произвольного выравнивания.
jcxz
Цитата(esaulenka @ Feb 12 2016, 22:02) *
Самый лаконичный способ, на мой взгляд.
Как бы в GCC такое сделать?..

Универсально (компиляторонезависимо):
class {
unsigned char raw[4];
//здесь добавить перегрузку операторов приведения типа к unsigned и присваивания unsigned
};
andrewkrot
Цитата(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) Совсем даже понятно, если не нравится арифметическое сложение, то можете объединить по ИЛИ, и ничего от этого не изменится - результат должен быть одинаковым
AVI-crak
Цитата(AlexeyT @ Feb 12 2016, 22:32) *
В каком именно месте происходит зависание, сказать не могу, процессор - 1986ВЕ1Т, там с дебагом туго.

Заставили?

Наверное проблема в том что промежуточные значения сохраняются в память,вместо того чтобы висеть в регистрах. Хотя для этого ну уж очень сильно постараться нужно, например объявить несколько глобальных переменных в регистрах мк - и превратить чип в реальный тормоз.
Решение в лоб - переменная uint32_t - для промежуточных вычислений.
И кстати, int - число со знаком равное размеру регистра мк, в этом случае с переносимостью кода будут проблемы, а так-же с простейшим сложением чисел без знака. На С можно любую ересть написать без юзанья int - и этот код будет выполняться на любом процессоре с одинаковым результатом.
demiurg_spb
Цитата(AlexeyT @ Feb 12 2016, 18:32) *
В каком именно месте происходит зависание, сказать не могу, процессор - 1986ВЕ1Т, там с дебагом туго.
Ничего туго там нет.
Пишется обработчик hard_fault и всё...
Главное, перед тем как применять этот проц, прочитать еррату, тогда вообще никаких сюрпризов.

Ну, а на счёт __packed для указателя, то в GCC аналогичного инструментария нет -
изучали эту тему несколько лет назад вдоль и поперёк.
Из того что удалось накопать сейчас - это __builtin_assume_aligned(ptr, align), но пока нет времени вникать как это использовать...
scifi
Цитата(demiurg_spb @ Feb 15 2016, 12:14) *
Ну, а на счёт __packed для указателя, то в GCC аналогичного инструментария нет -
изучали эту тему несколько лет назад вдоль и поперёк.

А я не очень-то понимаю, зачем этот инструментарий вообще где-то есть. Всё то же самое легко делается стандартными средствами языка (тот же memcpy), к тому же этот __packed внутри именно так и работает. ИМХО, это поощрение говнокода и привязка к компилятору, что не есть гут.
jcxz
Цитата(scifi @ Feb 15 2016, 15:40) *
А я не очень-то понимаю, зачем этот инструментарий вообще где-то есть. Всё то же самое легко делается стандартными средствами языка (тот же memcpy), к тому же этот __packed внутри именно так и работает. ИМХО, это поощрение говнокода и привязка к компилятору, что не есть гут.

В смысле - так и работает? И при чём тут говнокод? То, что этот метод не универсален между компиляторами - конечно плохо.
Чтение __packed uint для Cortex-M скомпилится в одну инструкцию LDR, для ARM7/9 - в набор LDRB/ORR.
А с memcpy() - в разы более громоздко + нужна доп. память. Что для embedded применений может быть критично.
Более универсальный метод - определение класса с перегруженными операторами приведения типа и присваивания. Иногда я поступаю так если нужна переносимость. Но __packed - проще.
demiurg_spb
Цитата(scifi @ Feb 15 2016, 12:40) *
А я не очень-то понимаю, зачем этот инструментарий вообще где-то есть.
Удобно, когда можно объявить указатель "на куда угодно" и работать через него без всяких танцев с бубном...
ИМХО никакого говнокода.
Сергей Борщ
Цитата(scifi @ Feb 15 2016, 11:40) *
ИМХО, это поощрение говнокода и привязка к компилятору, что не есть гут.
А по мне так наоборот - если происходит действие "обращение по указателю" - то логично было бы использовать предусмотренные для этого в языке средства разыменования указателя, а не захламлять исходник вызовами memcpy(). То, что этот указатель учитывает какие-то аппаратные особенности (невыровненный доступ), логично было бы как-то указать один раз при объявлении указателя (тот же __packed), а не распылять по исходнику в виде memcpy() и надеяться, что программист не забудет именно этот указатель использовать через memcpy().

В gcc можно обернуть искомые данные в упакованную структуру и обращаться по указателю на эту структуру.
dimka76
Цитата(demiurg_spb @ Feb 15 2016, 12:14) *
Ну, а на счёт __packed для указателя, то в GCC аналогичного инструментария нет -
изучали эту тему несколько лет назад вдоль и поперёк.
Из того что удалось накопать сейчас - это __builtin_assume_aligned(ptr, align), но пока нет времени вникать как это использовать...


Код
typedef volatile uint32_t REG32;
#define pREG32 (REG32 *)
#define USB_TXDATA                                (*(pREG32 (0x4002001C)))

uint8_t *pData;

USB_TXDATA = *((uint32_t __attribute__((packed)) *)pData);
scifi
Цитата(dimka76 @ Feb 15 2016, 14:19) *
Код
USB_TXDATA = *((uint32_t __attribute__((packed)) *)pData);

Как мёртвому припарка, то есть никакого эффекта. Собственно, и не должно работать, так как мануал пишет, что эта штука работает только с объявлением структуры, объединения или перечисления.
dimka76
Цитата(scifi @ Feb 15 2016, 14:29) *
Как мёртвому припарка, то есть никакого эффекта. Собственно, и не должно работать, так как мануал пишет, что эта штука работает только с объявлением структуры, объединения или перечисления.


Я взял это из примера от NXP.
scifi
Цитата(dimka76 @ Feb 15 2016, 14:34) *
Я взял это из примера от NXP.

Ну и отлично. Передавайте им привет и попросите впредь не говнокодить.
demiurg_spb
Цитата(scifi @ Feb 15 2016, 14:36) *
Передавайте им привет и попросите впредь не говнокодить.
Если этот пример для ARM компилятора, то имеет место быть...
А для gcc это не проходит, поэтому плохой пример NXP подаёт.
zltigo
QUOTE (Сергей Борщ @ Feb 15 2016, 12:43) *
В gcc можно обернуть искомые данные в упакованную структуру и обращаться по указателю на эту структуру.

А поскольку так можно делать на любом компиляторе, то так не только можно, но и следует делать всегда.
AVI-crak
Даже в случае безумного С кода, на асме получается необходимый минимум. В даже если проц не может читать/писать не выровненное - этот кусок он обязан выполнить.

Код
    ldr      r1, =адрес_char
    mov     r3, #0
    ldrb    r0, [r1], #4
    add     r3, r3, r0,
    ldrb    r0, [r1], #4
    add     r3, r3, r0, lsl #8
    ldrb    r0, [r1], #4
    add     r3, r3, r0, lsl #16
    ldrb    r0, [r1], #4
    add     r3, r3, r0, lsl #24
    ldr     r1, =адрес_uint32_t
    str     r3, [r1]
scifi
Цитата(AVI-crak @ Feb 15 2016, 18:19) *
Даже в случае безумного С кода, на асме получается необходимый минимум.

И это тоже. Прогресс в компиляторостроении привёл к тому, что вот эти стенания "а как же эти лишние две инструкции?" - зачастую устаревшая выдумка. Но даже если не так, пара лишних тактов и байтов вредит крайне редко. Короче, "преждевременная оптимизация", если говорить без матюков, но иметь в виду именно их smile3009.gif
zltigo
QUOTE (scifi @ Feb 15 2016, 20:02) *
И это тоже. Прогресс в компиляторостроении привёл к тому, что вот эти стенания "а как же эти лишние две инструкции?" - зачастую устаревшая выдумка. Но даже если не так, пара лишних тактов и байтов вредит крайне редко. Короче, "преждевременная оптимизация", если говорить без матюков, но иметь в виду именно их smile3009.gif

К чему в очередной раз поминание древней глупости - "преждевременная оптимизация" ?
http://electronix.ru/forum/index.php?showt...t&p=1348755
scifi
Цитата(zltigo @ Feb 15 2016, 21:44) *
К чему в очередной раз поминание древней глупости - "преждевременная оптимизация" ?
http://electronix.ru/forum/index.php?showt...t&p=1348755

Нет времени отвечать на ваши глупости. Кто имеет уши - тот услышит.
zltigo
QUOTE (scifi @ Feb 15 2016, 21:41) *
Нет времени...

Не сомневался sm.gif
jcxz
Цитата(scifi @ Feb 16 2016, 00:02) *
И это тоже. Прогресс в компиляторостроении привёл к тому, что вот эти стенания "а как же эти лишние две инструкции?" - зачастую устаревшая выдумка

Типичный аргумент кодера-форточника, создающего шедевры, способные показом обычного диалога загрузить intel-i7 на 100% на минуту.
Цитата(scifi @ Feb 16 2016, 00:02) *
Но даже не так, пара лишних тактов и байтов вредит крайне редко. Короче, "преждевременная оптимизация", если говорить без матюков, но иметь в виду именно их smile3009.gif

Предположим: нужна функция, инкрементирующая пакованный int. С __packed на Cortex-M это будет:
Код
LDR R1, [R0]
ADDS R1, R1, #1
STR R1, [R0]
BX LR

В случае с memcpy будет: создание стекового фрейма, копирование, инкремент, опять копирование, удаление стекового фрейма - итого:
не на пару байт, а во много раз (!!!) дольше + занимает доп.регистры + доп.стек.
scifi
Цитата(jcxz @ Feb 16 2016, 02:34) *
Предположим: нужна функция, инкрементирующая пакованный int. С __packed на Cortex-M это будет:
Код
LDR R1, [R0]
ADDS R1, R1, #1
STR R1, [R0]
BX LR

Попробовал на своём Cortex-M0. Не работает crying.gif

Цитата(jcxz @ Feb 16 2016, 02:34) *
В случае с memcpy будет: создание стекового фрейма, копирование, инкремент, опять копирование, удаление стекового фрейма - итого:
не на пару байт, а во много раз (!!!) дольше + занимает доп.регистры + доп.стек.

Глупость какая. Только что попробовал на Cortex-M3: как и положено, вместо memcpy подставляет LDR/STR.

Цитата(Сергей Борщ @ Feb 15 2016, 13:43) *
А по мне так наоборот - если происходит действие "обращение по указателю" - то логично было бы использовать предусмотренные для этого в языке средства разыменования указателя, а не захламлять исходник вызовами memcpy(). То, что этот указатель учитывает какие-то аппаратные особенности (невыровненный доступ), логично было бы как-то указать один раз при объявлении указателя (тот же __packed), а не распылять по исходнику в виде memcpy() и надеяться, что программист не забудет именно этот указатель использовать через memcpy().

В gcc можно обернуть искомые данные в упакованную структуру и обращаться по указателю на эту структуру.

Наверное, всё дело в том, что мне не доводилось писать код с невыровненным доступом, потому и удивляюсь. А ради одного-двух случаев в коде я точно не стал бы городить packed, а сделал бы memcpy. Хотя могу представить себе такой код - lwip, к примеру. Там нужно постоянно обращаться к полям пакетов, и там повсеместно используются упакованные структуры. Альтернатива - сделать функции доступа к полям через указание смещений, но это точно будет выглядеть коряво на фоне упакованных структур, так что принято.
zltigo
QUOTE (scifi @ Feb 16 2016, 10:36) *
Наверное, всё дело в том, что мне не доводилось писать код с невыровненным доступом, потому и удивляюсь.

Практически абсолютно любой протокол обмена требует обращения ко всяким разным полям (в том числе и битовым )во фрейме, то что они не выровнееные это практически наверняка и если не писать разбоку и формирование в стиле "третий бит в пятом байте слева" (за что вообще-то надо сразу чего нибудь оторвать, что болтается), то сразу становятся необходимыми структуры и обьединения. Причем, если платформа не восьмибитовая, то сразу возникают понятия раковки стуктур и на многих платформах невыровненный доступ. Но проблема доступа в таком случае сразу скрывает компилятор.
Но в общем структуры организуются СОВЕРШЕННО не для того, что-бы бороться с выравниваним и заявление:
QUOTE
А ради одного-двух случаев в коде я точно не стал бы городить packed

более чем....
Kabdim
Цитата(dimka76 @ Feb 15 2016, 14:19) *
Код
typedef volatile uint32_t REG32;
#define pREG32 (REG32 *)
#define USB_TXDATA                                (*(pREG32 (0x4002001C)))

uint8_t *pData;

USB_TXDATA = *((uint32_t __attribute__((packed)) *)pData);

В тех примерах от NXP которые у меня:
Код
#if defined(__GNUC__)   // Code Red tools

...

// The following two typedefs are required as GCC does
// not directly support a method of hinting that a variable
// (as opposed to a structure) should be accessed with
// the assumption that it is unaligned, which can be done
// in Keil using, for example, __packed uint32_t *p;
typedef struct { uint32_t value __attribute__(( packed ));
}unaligned_uint32;

typedef struct { uint16_t value __attribute__(( packed ));
}unaligned_uint16;

...

А использование что-то вроде такого:
Код
#if defined(__GNUC__)
          (( unaligned_uint16 *)EP0Buf)->value = (USB_EndPointHalt & m) ? 1 : 0;;
#else
          *((__packed uint16_t *)EP0Buf) = (USB_EndPointHalt & m) ? 1 : 0;
#endif
scifi
Цитата(Kabdim @ Feb 16 2016, 14:07) *
А использование что-то вроде такого:
Код
#if defined(__GNUC__)
          (( unaligned_uint16 *)EP0Buf)->value = (USB_EndPointHalt & m) ? 1 : 0;;
#else
          *((__packed uint16_t *)EP0Buf) = (USB_EndPointHalt & m) ? 1 : 0;
#endif

Интересно, зачем так? Ведь гнусишный вариант вполне может работать и с RealView.
Kabdim
Цитата(scifi @ Feb 16 2016, 14:32) *
Интересно, зачем так? Ведь гнусишный вариант вполне может работать и с RealView.

Там были глупостей и ошибки похлеще, но работало. Подозреваю что вначале написали на Кейле, а потом другой человек отпортировали на gcc не слишком задумываясь, лишь бы работало.
demiurg_spb
Цитата(jcxz @ Feb 16 2016, 02:34) *
В случае с memcpy будет: создание стекового фрейма...
Такого ужаса уже давно нет.
По крайней мере, в gcc практически все библиотечные функции за'builtin'ены, и компилятор встраивает и разворачивает их максимально гибко, вплоть до того, что sin(const) и иже с ним считается чуть-ли не на этапе препроцессинга и может использоваться даже для инициализации констант.

Цитата(Kabdim @ Feb 16 2016, 14:07) *
Код
          typedef struct { uint16_t value __attribute__(( packed ));}unaligned_uint16_t;

          (( unaligned_uint16_t *)EP0Buf)->value = 1;
С выкрутасом решение, но читаемость хромает.
Если запрятать это в макрос, то читаемость поднимется в разы...
Спасибо! Может когда-нибудь пригодится.
jcxz
Цитата(demiurg_spb @ Feb 16 2016, 19:08) *
Такого ужаса уже давно нет.
По крайней мере, в gcc практически все библиотечные функции за'builtin'ены, и компилятор встраивает и разворачивает их максимально гибко, вплоть до того, что sin(const) и иже с ним считается чуть-ли не на этапе препроцессинга и может использоваться даже для инициализации констант.

Часто приходится компилить без оптимизации, для отладки и т.п. С отключенной оптимизацией разве развернёт?
Один фиг - писать все эти memcpy() для доступа к одной пакованной переменной - это как раз глупо и слишком громоздко (снижает читаемость исходника).
demiurg_spb
Цитата(jcxz @ Feb 16 2016, 16:59) *
Часто приходится компилить без оптимизации, для отладки и т.п. С отключенной оптимизацией разве развернёт?
Не знаю, т.к. меня этот вопрос вообще не заботит.
Tarbal
Цитата(AlexeyT @ Feb 12 2016, 18:05) *
Задача такая - есть массив 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.

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


А ваш процессор Big endian или little endian? Вроде в АРМ это переключить можно, хотя чаще всего он он little endian.
Второй вопрос в вашем массиве данные Big endian или little endian?
_pv
Цитата(jcxz @ Feb 16 2016, 19:59) *
Один фиг - писать все эти memcpy() для доступа к одной пакованной переменной - это как раз глупо и слишком громоздко (снижает читаемость исходника).

ради одной пакованной переменной писать кучу #if при объявлении, с различными прагмами/атрибутами для разных компиляторов не менее глупо.
лучше уж макрос или инлайн функция которая возвращает нормальный int из невыровненного адреса.

в единственном случае где могут понадобится упакованные структуры и где без этого вполне можно обойтись - в случае с протоколами обмена, там всё равно все доступы к структуре будут обёрнуты в hton / ntoh. ну будет еще одна обёртка для выравнивания, тоже мне проблема.
zltigo
QUOTE (_pv @ Feb 16 2016, 20:33) *
ради одной пакованной переменной писать кучу #if при объявлении, с различными прагмами/атрибутами для разных компиляторов не менее глупо.
лучше уж макрос или инлайн функция которая возвращает нормальный int из невыровненного адреса.

Городить какую-то функцию, которая будет разбитаться как именно невыровнен адрес а может и выровнен.... тода уж memcpy() - эта занимается тем-же самым, но понятно, что делает.
И все это ради того, что-бы отвергать великолепный механизм паковки и доступа к структурам. Дурдом. Но понятный после этого заявления:
QUOTE
в единственном случае где могут понадобится упакованные структуры и где без этого вполне можно обойтись - в случае с протоколами обмена

становится понятным, что задачи обмена данными бесконечно далеки от Вас и "контроллеров светодиодов".
QUOTE
, там всё равно все доступы к структуре будут обёрнуты в hton / ntoh.

C какого бодуна, если это зависит от протокола и контрорлера.

_pv
Цитата(zltigo @ Feb 17 2016, 01:16) *
Городить какую-то функцию, которая будет разбитаться как именно невыровнен адрес а может и выровнен.... тода уж memcpy() - эта занимается тем-же самым, но понятно, что делает.
И все это ради того, что-бы отвергать великолепный механизм паковки и доступа к структурам. Дурдом.

Этот великолепный механизм - костыли которые в каждом компиляторе сделаны (и хорошо если в каждом) по своему.
Вон у TI, TCP стэк для msp430, как-то обошлись без великолепных механизмов.
И раз уж Вы так близки к задачам обмена данными, не приведёте код объявления упакованной структуры который любой С компилятор поймёт?
Цитата(zltigo @ Feb 17 2016, 01:16) *
C какого бодуна, если это зависит от протокола и контрорлера.

endiannes у всех всех контроллеров вдруг стала одинаковая и так получиться так что она будет отличаться от заданной в протоколе никак не может?
zltigo
QUOTE (_pv @ Feb 16 2016, 22:16) *
И раз уж Вы так близки к задачам обмена данными, не приведёте код объявления упакованной структуры который любой С компилятор поймёт?


http://electronix.ru/forum/index.php?showt...st&p=268461

В файлы постепенно добавляете все компиляторы с которыми работаете. Вот так просто.

QUOTE
Вон у TI, TCP стэк для msp430, как-то обошлись без великолепных механизмов.

Не смотрел, по причине наличия уже лет, как 25 своих нескольких стеков. Но охотно верю, что через анус можно сделать все.
Вопрос зачем?
QUOTE
endiannes у всех всех контроллеров вдруг стала одинаковая и так получиться так что она будет отличаться от заданной в протоколе никак не может?

Это Вы сами с собой спорите опровергая свое утверждение, что в разборщиках протоколов
QUOTE
...всё равно все доступы к структуре будут обёрнуты в hton / ntoh.

?
Конкретные протоколы могут создаватья и с учетом уже конкретных платформ. Вот я прямо сейчас сочиняю маршрутизируемый для RS485 для трех платформ. Получается на весь протокол одно ntohs() да и то не в явном виде.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.