Why does this compile without errors?

Can someone explain why this program compiles without errors. It is clearly wrong. I am using the latest version: 1.8.1.

void test(int * p) {
*p = 0;
}

void setup() {
int i;
test(i);
}

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

}

You get a bunch of warnings for this code.

SomeWhere\WhyDoesItCompile\WhyDoesItCompile.ino: In function 'void setup()':

SomeWhere\WhyDoesItCompile\WhyDoesItCompile.ino:7:9: warning: invalid conversion from 'int' to 'int*' [-fpermissive]

   test(i);

         ^

SomeWhere\WhyDoesItCompile\WhyDoesItCompile.ino:1:6: note: initializing argument 1 of 'void test(int*)'

 void test(int * p) {

      ^

SomeWhere\WhyDoesItCompile\WhyDoesItCompile.ino:7:9: warning: 'i' is used uninitialized in this function [-Wuninitialized]

   test(i);

         ^

JohnGaby:
Can someone explain why this program compiles without errors.

Probably because -fpermissive is specified on the commandline of the compiler.

Thanks for the quick replies. I am just using the default options. Can you tell me how to turn the -fpermissive option off?

Thanks

JohnGaby:
Can you tell me how to turn the -fpermissive option off?

No.

I remove all warnings before running a sketch, so I don't need to change the option.

I am not sure what you mean when you say that you 'remove all warnings'. Do you mean that you always fix warnings? If so, I am in complete agreement with that and always do the same. However when I compile this code with the default options for version 1.8.1 of the Arduino software, I get neither warnings nor errors. It tells me that everything is fine, when it is clearly not.

Thanks.

So switch on the warnings.

Ctrl-, or Files/Settings (I'm not shure about the naming, I'm using a German version)

Compiler-Warnings All.

I apologize, I am apparently completely blind. I swear that I searched for such an option in the settings but I just could not see it.

Thanks much.

I personally don't like the combination of -fpermissive and default-switched-off-warnings. :wink:

Yes, I did not expect that. I really did not think that the default settings would be such that this code would compile at all, much less without warnings.

Yes, one of the whole points of modern languages is to do type checking (the stricter the better) and to turn all of that off by default makes little sense to me. However, now that I have turned it back on, I can see why they might have done that. Many of the libraries that I am using generate a copious amounts of warnings and they probably didn't want people to see all of that.

Delta_G:

void test(int * p) {

*p = 0;
}




The compiler probably optimized this to an empty function and then removed it since it doesn't actually do anything. Hence it compiles with no problems.

It's not optimization, but an implicit conversion between types int and int*. This produces a warning (due to the -fpermissive flag already mentioned) which is hidden unless you turn on verbose compilation.

Jiggy-Ninja:
It's not optimization, but an implicit conversion between types int and int*. This produces a warning (due to the -fpermissive flag already mentioned) which is hidden unless you turn on verbose compilation.

It flags the warning when parsing the code, but also likely optimizes it completely away, later in the compilation process, as the code, overall, does nothing with any side-effects, as the code sets a variable, but that variable is then never read. If it were declared volatile, perhaps it would not be optimized out, but as it is, I'd guess it would be.

Regards,
Ray L.

void test(int * p) {
  *p = 0;
}

int tValue = 0x1234;

void setup() {
  Serial.begin(250000);
  int i = &tValue;
  test(i);
  Serial.print(tValue, HEX);
}
void loop() {}

0

RayLivingston:
It flags the warning when parsing the code, but also likely optimizes it completely away, later in the compilation process, as the code, overall, does nothing with any side-effects, as the code sets a variable, but that variable is then never read. If it were declared volatile, perhaps it would not be optimized out, but as it is, I'd guess it would be.

Regards,
Ray L.

No, it's writing 0 to a dereferenced pointer (note the *). I can't imagine any reason for a compiler optimizer to decide to remove that.

Jiggy-Ninja:
No, it's writing 0 to a dereferenced pointer (note the *). I can't imagine any reason for a compiler optimizer to decide to remove that.

Well, whether you can imagine any reason or not, it does. The sketch in the OP compiles to 444 bytes. A completely empty sketch also compiles to 444 bytes. Modern compilers are very smart about optimization...

Regards,
Ray L.

Delta_G:

void test(int * p) {

*p = 0;
}




The compiler probably optimized this to an empty function and then removed it since it doesn't actually do anything. Hence it compiles with no problems.

This is most certainly not an empty function.

At a guess, the compiler permits test(i) because on the AVR int values and pointers are both 16 bit.

Many of the libraries that I am using generate a copious amounts of warnings and they probably didn't want people to see all of that.

Then, they should fix the libraries, not turn a blind eye to all the problems.

PaulS:
Then, they should fix the libraries, not turn a blind eye to all the problems.

No kidding. I have never used a C++ setup before that hides so many issues by default. Personally, I usually have most warnings turned on and have the compiler set to treat warnings as errors so I am forced to fix them. And I certainly don't enable an option which turns off type checking (i.e. -fpermissive).

And yes, I am aware that you can, under the right circumstances, copy a pointer into an integer and back to a pointer and have it work. However, you should be forced to use casts to tell the compiler that you actually know what you are doing (hopefully you do). Lacking the casts, that kind of code should always be flagged as an error, not a warning.

Thanks again for all your help.