недопустимое преобразование из ‘long int’ в ‘void (*) ()’ [-fpermissive]

Привет, я пишу немного модифицированный код для загрузчика для MCU. Модификация, которую я пытаюсь сделать — это запустить загрузчик даже для сброса сторожевого таймера.

Я использую этот прототип функции для определения адреса загрузчика и получаю сообщение об ошибке:

недопустимое преобразование из ‘long int’ в ‘void (*) ()’ [-fpermissive]

Мой код

#if defined ( __AVR_ATmega1284P__ )
void (*boot_start)(void) = 0xF000;
#elif defined ( __AVR_ATmega2560__ )
void (*boot_start)(void) = 0x1F000;
#endif

Где 0xF000 и 0x1F000 — области памяти. Я не получаю эту ошибку, если мой код `

void (*boot_start)(void) = 0x0000;

Зачем ??

0

Решение

Компилятор распознает 0xF000 как int и откажитесь от присвоения этого значения указателю. Вы должны привести это явно:

void (*boot_start)(void) = (void (*)())0xF000;
1

Другие решения

0x0000 — это просто другое имя для NULL, и оно будет скомпилировано нормально как значение указателя, но другие значения должны быть явно приведены к правильному типу.

3

Ответ, который я получил от форума AVRFreak,

ИСПОЛЬЗОВАТЬ TYPEDEF,

typedef void (*fptr_t)(void);

fptr_t boot_start = (fptr_t)0xF000;

...
boot_start();

В противном случае вы получаете предупреждение, потому что 0xF000 — это длинное int для AVR. Объект слева от «=» был указателем на функцию. Итак, вы пытаетесь присвоить целое число указателю. С думает, что это, вероятно, ошибка (часто это так!), Поэтому предупреждает вас. Способ, которым вы подавляете это предупреждение, заключается в том, чтобы сказать: «Нет, это число 0xF000 действительно является значением указателя». То, как вы делаете это с помощью Typecast. Теперь вы можете сделать это с (подождите):

void (*boot_start)(void) = (void(*)(void))0xF000;

Но, как вы можете видеть в этом, есть почти точно такая же (довольно сложная) структура по обе стороны от равных. Поэтому имеет смысл поместить все эти детали в один typedef и использовать его в нескольких местах.

Если бы тип функции был более сложным, это могло бы быть что-то вроде:

int (*boot_start)(char, long, int *) = (int (*)(char, long, int *))0xF000;

и это начинает выглядеть очень глупо — не только очень вероятно, что вы допустили ошибку при печати, это просто попытка вспомнить синтаксис, это настоящая боль! Таким образом, вы используете typedef для определения интерфейса функции только один раз:

typedef int (*myfn_t)(char, long, int *);

myfn_t boot_start  = (myfn_t))0xF000;

и это становится легче набирать и легче управлять. Если позже вы добавите четвертый параметр char ** в функцию, то теперь вы делаете это только в одном месте — typedef.

Спасибо клиенту Лоусону и Юрию.

0