Reputation: 415
Is it possible to modify the contents of the memory address of the return value of a function? functions return the value of a locally defined variable.
In the following example, compiled for my machine (x86-64) without warnings:
#include <stdio.h>
int get_val1()
{
int ret = 1;
return ret;
}
int get_val2()
{
int ret = 2;
return ret;
}
int get_val3()
{
int ret = 3;
return ret;
}
void redefine_ints(int *val1, int *val2, int *val3) {
*val1 = 10;
*val2 = 11;
*val3 = 12;
}
void print_and_redefine_ints(int val1, int val2, int val3) {
printf("val1 %d val2 %d val3 %d\n", val1, val2, val3);
redefine_ints(&val1, &val2, &val3);
printf("rval1 %d rval2 %d rval3 %d\n", val1, val2, val3);
}
int main()
{
print_and_redefine_ints(get_val1(), get_val2(), get_val3());
return 0;
}
I get the next output:
val1 1 val2 2 val3 3
rval1 10 rval2 11 rval3 12
This is the expected output, but how is it possible? Where are these variables stored?
Upvotes: 6
Views: 460
Reputation: 134396
Is it possible to modify the contents of the memory address of the return (value) of a function?
No, it is not.
However, that is not the case here. In your code, the return values of get_val<n>()
function calls are stored in the function parameters int val1
, int val2
, int val3
. They are local to the called function. The lifetime of those variables are the function execution period.
Quoting C11
, chapter §6.2.1,
[...] If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. [....]
and, from §6.9.1, Function definition,
Each parameter has automatic storage duration; its identifier is an lvalue
Thus, just like any other local variable, you can modify the content of those variables using their address.
Upvotes: 3
Reputation: 234865
Yes this is well-defined C.
The anonymous temporary int
s created by get_val...()
have a lifetime contemporaneous with the entire statement in which they are created.
But note that you take a value copy of each of these int
s when you call print_and_redefine_ints
so there's nothing particularly special going on here.
(Note that you would not be able to bind pointers to the anonymous temporary int
s to int*
function parameters though.)
Upvotes: 5
Reputation: 15257
A draw may explain more than some text. I'll use only 1 get_val1()
in that example.
print_and_redefine_ints(get_val1());
|
|
[CALL]
|
|
V
int get_val1()
{
int ret = 1;<----------------------------------------------------+
return ret; |
} | |
| |
[COPY OF VALUE] |
| |
| |
+---+ |
| |
| |
V |
void print_and_redefine_ints(int val1) { |
printf("val1 %d\n"); ^ |
redefine_ints(&val1); | |
| +--------------------------------------------+ |
| | |
[POINTER AKA REFERENCE] | |
| | |
| | |
V | |
void redefine_ints(int *val1) { | |
*val1 = 10; //<---- the value is changed, then its referenced value (this one, NOT THIS ONE) is changed too
} |
|
+---+
|
[VALUE CHANGED]
|
|
V
printf("rval1 %d\n", val1);
printf("original val1 %d\n", get_val1()); //if you add this line, you'll notice the returned value of get_val1() is still 1
}
Upvotes: 5