Weird warning. Why?

I get a weird warning. I can't figure out why.

volatile uint8_t m;

uint8_t getNumber() {
  return 1;
}

void setup() {
  uint8_t n = getNumber;
  m = n;  // prevent optimizing away
}

void loop() {
  // put your main code here, to run repeatedly:
}

In output:

C:\Users\hanss\AppData\Local\Temp\.arduinoIDE-unsaved20251117-41564-18hm0vg.rt8p\sketch_dec17a\sketch_dec17a.ino: In function 'void setup()':
C:\Users\hanss\AppData\Local\Temp\.arduinoIDE-unsaved20251117-41564-18hm0vg.rt8p\sketch_dec17a\sketch_dec17a.ino:7:15: warning: invalid conversion from 'uint8_t (*)() {aka unsigned char (*)()}' to 'uint8_t {aka unsigned char}' [-fpermissive]
   // put your main code here, to run repeatedly:
               ^~~~~~~~~

You left off parentheses changing what that line of code does for the worse.

a7

Hi @stitech. The reason it is "weird" is because the sketch is in an unsaved state, where the file on disk does not match the code being compiled.

If you save the sketch and then compile again, the warning will make more sense:

C:\Users\per\Documents\Arduino\sketch_dec17b\sketch_dec17b.ino: In function 'void setup()':
C:\Users\per\Documents\Arduino\sketch_dec17b\sketch_dec17b.ino:8:15: warning: invalid conversion from 'uint8_t (*)() {aka unsigned char (*)()}' to 'uint8_t {aka unsigned char}' [-fpermissive]
   uint8_t n = getNumber;
               ^~~~~~~~~

Possibly because you missed the brackets?

uint8_t n = getNumber();

Otherwise its trying to assign the address of the function to n.

Sorry, @ptillisch, @alto777 posts crossed!

Parenthesis! (Banging my head to the wall.)

@alto777 actually won the race. I removed the duplicate content from my post once I noticed it had already been posted, but left in the unique explanation re: the unfortunate warning content mismatch caused by having an unsaved sketch.

Saved it without parenthesis and compiled again, almost same warning, still weird.

C:\Users\hanss\Documents\Arduino\sketch_dec17a\sketch_dec17a.ino: In function 'void setup()':
C:\Users\hanss\Documents\Arduino\sketch_dec17a\sketch_dec17a.ino:7:15: warning: invalid conversion from 'uint8_t (*)() {aka unsigned char (*)()}' to 'uint8_t {aka unsigned char}' [-fpermissive]
   uint8_t n = getNumber;
               ^~~~~~~~~

Yeah, it's really important to win races like this, especially if one gets the coveted solution mark.

When a contributor racks up enough check marks, she gets a free Arduino UNO!

a7

I assumed that you were referring to the irrelevant line of the sketch code being referenced by the warning:

Note that the correct line of code is now shown in the warning:

I suppose the somewhat cryptic "invalid conversion from 'uint8_t (*)() {aka unsigned char (*)()}' to 'uint8_t {aka unsigned char}' [-fpermissive]" warning itself might also be described as "weird".

More weirdness: according to the disassembled program, the value 0x48 is stored in the only RAM location used.
Apparently a compiler warning doesn't mean "I got the meaning anyway." but "You probably won't get what you wanted."

Absolutely. The compiler’s really saying “I did what you told me because it’s not invalid to do so, but history says that’s unlikely to be what you wanted - so go reread your code and think about it!”

it's actually very clear and not weird if you understand types in C++...

In C++, the name of a function is actually a pointer to that function.

When you write

uint8_t n = getNumber;

you are assigning the address of the function getNumber to a variable n of type uint8_t.

The type of the function getNumber itself is uint8_t(), which means “a function taking no arguments and returning a uint8_t.”

When you use the function name without parentheses, it decays to a pointer to the function, so the type is uint8_t (*)().

this is why you see

warning: invalid conversion from uint8_t (*)()  to 'uint8_t 

This is technically a type mismatch, but C++ allows it by truncating the pointer (an address in memory) to fit into the single byte. Since the compiler can do it (edit: only because of the -fpermissive flag) , it is not an error, only a warning, because the resulting value is almost certainly meaningless but the code is still valid C++ syntax.

Still learning. Thank you.

It is an error, but the :angry: :enraged_face: :angry: -fpermissive :angry: :enraged_face: :angry: option downgrades it to a warning.

correct - I should have mentioned that . added

The flag exists for backward compatibility and pragmatism. Large amounts of old C and non-conforming C++ code rely on implicit or invalid conversions that were accepted by older compilers or by C but are illegal in C++. Rejecting all of that code would make migration very costly.

-fpermissive lets the compiler keep compiling such code by turning some errors into warnings, so developers can get a build, run tests, and then fix the code incrementally. It is not meant to make the code legitimate or correct, only to keep legacy or sloppy code compiling.

There is a proposal to remove the -fpermissive flag from the compilation command templates of the "Arduino AVR Boards" platform here: