简体   繁体   中英

invalid conversion from 'long int' to 'void (*)()' [-fpermissive]

Hi I am writing little modified code for the bootloader for MCU's. The modification I am trying to do is power the boot loader even for an watchdog timer reset.

I am using this function prototype to define the address of the boot loader and I get the error :

invalid conversion from 'long int' to 'void (*)()' [-fpermissive]

My code is

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

Where the 0xF000 and 0x1F000 are memory spaces. I don't get this error if my code is `

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

Why ??

0x0000只是NULL的另一个名称,可以将ok编译为指针值,但是其他值需要显式转换为正确的类型。

Compiler recognize 0xF000 as int and discard assigning this value to pointer. You should cast it explicitly:

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

The answer that I got from AVRFreak forum,

USE TYPEDEF,

typedef void (*fptr_t)(void);

fptr_t boot_start = (fptr_t)0xF000;

...
  boot_start();

The reason you get the warning otherwise is that 0xF000 is a long int for an AVR. The thing on the left of '=' was a pointer to a function. So you are trying to assign an integer to a pointer. C thinks this is probably a mistake (often it is!) so it warns you. The way you quell that warning is to say "no this 0xF000 number really is a pointer value". The way you do that is with a typecast. Now you could do this with (wait for it):

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

But as you can see in that there is almost exactly the same (quite complex) structure on both side of the equals. So it makes sense to put all that detail into one single typedef and use it in multiple places.

If the function type were more complex this might even be something like:

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

and this starts to look very silly indeed - not only is it very likely you make a typing error it's just trying to remember the syntax here is a real pain! So you use typedef to define the function interface just once:

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

myfn_t boot_start  = (myfn_t))0xF000;

and that gets to be easier to type and easier to manage. If you later add a fourth char ** parameter to the function you now do it in just one place - the typedef.

Thanks to C Lawson and Yuriy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM