|Always acknowledge your return values! Or don't. But do. [message #7689]
||Sun, 05 March 2017 20:19 |
|I was wondering if anyone would like to augment the information I will receive from a series of hopeful google searches with their own answer to this question:|
When I declare a function which returns a value, but then I call that function in my code without assigning the returned value to anything... what happens to it? I don't get a compiler warning even with the extra, and so forth. Where in the green digital void does this value end up and why does the codeGod, usually so viciously fickle and cruel suddenly deem such an oversight perfectly acceptable?!
savageBurn *makeBurnMoreSavage(savageBurn *mildBurn, int desiredBurnSeverity);
But then I call the function without assigning the augmented burn, thusly:
savageBurn *lukeWarmInsult = newSavageBurn(char* iDoNotLikeYourInsults);
makeBurnMoreSavage(savageBurn *lukeWarmInsult, *9001);
The original value is altered, and all is well. However, I wonder what becomes of the pointer that was supposed to be returned logically, but is ignored syntactically. Poor little guy... all alone out there... probably cold... scared.
[Updated on: Mon, 06 March 2017 14:33] by Moderator
Codes exclusively in the nude.
Report message to a moderator
|Re: Always acknowledge your return values! Or don't. But do. [message #7859 is a reply to message #7751]
||Thu, 16 March 2017 14:33 |
|The explanation really requires a look at assembly.|
Here's an example. Say you have this C program:
int add1(int x)
return 1 + x;
int a = 1;
int result = add1(a);
printf("%d + 1 = %d\n", a, result);
It produces the result:
Now let's have a look at the gcc x86_64 assembly.
I have added some comments to attempt to explain what is going on.
In case you have never encountered assembly before, note that
mov a, b
means move b into a.
NOT a into b.
It's a little backwards.
mov eax, edi # move the argument int eax
add eax, 1 # add one to eax
# return value always put into eax
.string "%d + 1 = %d\n"
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-8], 1 # (rbp - 8) is the address of a.  means dereference
# We are basically doing *(&a) = 1
mov edi, DWORD PTR [rbp-8] # add1's first argument needs to be in the edi 32-bit register
call add1 # Call the function
# Result of a function is always stored in the eax register
mov DWORD PTR [rbp-4], eax # Move the result out of the register and into the 'result' variable
# argumets to printf need to be stored in order from left
# to right in registers edi esi edx
mov edi, OFFSET FLAT:.formatString # copy format string
mov esi, DWORD PTR [rbp-8] # copy variable 'a' into register eax
mov edx, DWORD PTR [rbp-4] # copy variable 'result' into register edx
mov eax, 0 # main returns 0
The gist of what this is saying is that the return value is always placed the eax register, thus the calling function is free to completely ignore whatever is placed in that register after having called a function. It's perfectly safe and legal to do so. Gcc just wants to let you know that you declared a function which is supposed to return something, but you are ignoring it, which is possibly an error.
"Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration." -- Stan Kelly-Bootle
Report message to a moderator