Could someone explain this to me please? See my sketch below. The first call to add1000() does as expected - it adds 1000. The second 'call' to add1000 without brackets compiles without problems but does NOT execute the function. I'm running on a Nano and I've seen the same on an ESP32. This caused a nasty bug in one of my projects!
int i = 1;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.print("i is ");
Serial.println(i);
add1000();
Serial.print("i is ");
Serial.println(i);
add1000;
Serial.print("i is ");
Serial.println(i);
}
boolean add1000() {
i += 1000;
return true;
}
void loop() {
// put your main code here, to run repeatedly:
}
If you don't put the brackets, the function does not get called, but the address of the function is returned. In this case, that returned address is simply discarded, because you didn't print it or assign it to a variable.
Because it's basically getting the address of the function and immediately discarding it.
C/C++ often lets you do stupid stuff without complaining. In this respect, it's not a great language for beginners, but it was chosen for Arduino because it was the only language that was suitable, given the extremely limited resources of older Arduino boards.
I don't know if the IDE warnings turned up would have helped, but it is something that will drop you a warning.
I used -Wall, which gives you more I think than the IDE lets you say you want.
Either way, I recommend going to the IDE preferences and cranking up its ability to help with this sort of thing, which as @PaulRB noted C is kinda notorious for.
Some of the things you may see make no sense but are useful language features. Likened to a gun, powerful and nothing to keep you from shooting youself in the foot.
/var/folders/gz/t92bgl156gdf2066kn0xpc7w0000gq/T/arduino_modified_sketch_828160/sketch_jan30a.ino: In function 'void setup()':
/var/folders/gz/t92bgl156gdf2066kn0xpc7w0000gq/T/arduino_modified_sketch_828160/sketch_jan30a.ino:8:7: warning: statement is a reference, not call, to function 'foo' [-Waddress]
foo;
^
/var/folders/gz/t92bgl156gdf2066kn0xpc7w0000gq/T/arduino_modified_sketch_828160/sketch_jan30a.ino:8:7: warning: statement has no effect [-Wunused-value]
Under File | Preferences (or the Settings under the app menu on Mac), Compiler warnings has four levels
None
Default
More
All
void setup() {
3;
3 + 4;
loop;
}
void loop() {}
I only get the warning with More or All
sketch_jan30b.ino: In function 'void setup()':
sketch_jan30b.ino:2:4: warning: statement has no effect [-Wunused-value]
3;
^
sketch_jan30b.ino:3:5: warning: statement has no effect [-Wunused-value]
3 + 4;
~~^~~
sketch_jan30b.ino:4:7: warning: statement is a reference, not call, to function 'loop' [-Waddress]
loop;
^
sketch_jan30b.ino:4:7: warning: statement has no effect [-Wunused-value]
Any valid expression is a valid statement in C. The expression by itself may have "no effect" though. Will the compiler actually generate code to add 3 and 4? It may actually be "optimized away" and skip it.
So consider setting it to More (or All) and see if you get "too many warnings"
Well think about it. How else can one assign callback functions? You need the function's address to save off the pointer to your assigned callback function.
Never not compile with warnings! At work it's -Wall and -Werror, with some specific warnings exempted. (OP, the above means "turn on all warnings" and "upgrade all warnings to errors". In other words, do not produce a binary if there are any warnings.)
When I was paid to do this stuff, my shop of 300 had no choice as I built the tool set and did as you say. Reason, the language we used (not C) had a @mistertransistor Informational level error that actually made a program crash!
If it's just for your amusement do whatever you want, but if it's professional work EVERY compiler message is a potential error and it will happen on a long weekend with their bread and butter application unless Murphy has died.
No its not like Serial.print return value. Calling Serial print does something. This does nothing and I cannot think of a circumstance when it would be anything except an error. However, the creators of the language have allowed it and the compiler only issues a warning.
C does have some curious design choices, I am wondering why this one was made. I haven't found much detail info on the particular choices made. However, in general terms, the creators seemed to like the abstraction of new languages like ALGOL, but having had a bad experience with PL/I, they wanted something practical to implement, given the resource constraints at the time.
So I can see that making assignment ("=") an operator, instead of a statement, allows for some simplifications to the compiler, as well as quirky things like assignment in expressions.
Also, in original C, all functions returned int so a struct language might require you to declare a dummy return variable, even if the function returned no value.
Yes, but it is sensible for functions to sometimes have their values ignored. It is never sensible for statements that consist only of a value to be ignored.
This is one of those things that probably wasn't implemented originally because of time constraints, and now can't be fixed because there's too much code out there there might break if you did fix it.
I've come to grips with C, and I have my own way of looking at it, which evidently is not something I can write down. But I asked chatGPT for help, we had a freewheeling convo after this prompt
Why aren't lines of code that do nothing, have no effect whatsoever, no considered errors in C++?
And I asked at the end for a short summary of what it came up with: