I was doing some exercises when I saw the following: I have this function:
bool film_equals(tFilm* film1, tFilm* film2);
And when I wanted to use it, I didn't need it with pointers, so it would be something like this:
if( film_equals(&film,&temporal->e.film)==true)
{
isFavorited=true;
}
Being tFilm film
a parameter of the function and temporal->e.film
a node whose value is the movie
My question here is... why does it fail if I don't put & in front of the parameters? What exactly does this mean for my values?
So you shouldn't use pointers:
If you want instances instead of pointers, omit the asterisk (
*
):The et operator gets a pointer to an instance. So if you have an object of type
tFilm
calledfilm
, when you apply the operator et:&film
you get a pointer totFilm
(tFilm*
) which is exactly what your function asksfilm_ecuals
for and so it fails if it doesn't provide arguments that match the signature of the function. function.Let's imagine that our structure
tFilm
was declared like this:Then, we are going to suppose that the offsets of each member of the structure
tFilm
are the following:The only thing that the offset indicates is the displacement necessary to be able to add it to the base address (that of the first member) of the structure and thus obtain the memory address of some member of the structure
tFilm
.Ready, having this information, we can easily understand the following question:
To answer the question, I will pose the following code:
In the example above, we define two implicit pointers (
film1
andfilm2
) and initialize the structure with default values.Additionally, we will assume the memory addresses of the two structures we have created in memory:
When this function is called:
What would we be going through?
Basically what we are passing is the base address of the struct
tFilm
.And this is because, because the code above actually converts to this:
So that later, the compiler interprets it in this way (this is the way it would be read at a low level):
If you notice, the member
price
is actually replaced by its respectiveoffset
one (obviously this is calculated by the compiler itself).So, if we know that the implicit pointer
film1
has the base address (in this case it is0x4
) of the structuretFilm
, just by adding a0
to said address, we would obtain the memory address of the first member and this also applies to the implicit pointerfilm2
.So, this means that the first parameter of the function
film_equals
will have the address stored0x4
(which corresponds to the memory block pointed to byfilm1
).The same would happen with the second parameter, it would be passing the address
0x24
(because it corresponds to the address of the first member pointed tofilm2
).Now understanding this, we can conclude that if we were to remove the ampersand
&
in the following call:What we would be passing is the content of the first member of the structure
tFilm
. Basically the equivalent code would be like this:Which in turn, the compiler interprets it this way:
So, we realize, what we are passing in this case, is the content that has both memory addresses (
0x4
corresponds to the first member of the block1 it pointed tofilm1
and0x24
the block2 it pointed tofilm2
).And if we check our table that we had previously placed, it tells us what the first parameter of the function would receive,
film_equals
which would be a2
(this was the value that the memberprice
of the first memory block pointed to hadfilm1
) and the second parameter would receive a3
(this was the value held by the memberprice
of the second memory block pointed to byfilm2
).However, this is dangerous, because the addresses
0x2
are0x3
received by the function pointers, but then the routine would access those addresses that we don't even know if they belong to the program or not, that is, the application would stop working, because the system operative will not allow you to access an address in which you do not have access.FOR THAT REASON it is NECESSARY to prepend the ampersand
&
to the pointersfilm1
,film2
otherwise a segmentation fault will occur .Now, let's continue with the next question:
This could only happen if our function was defined like this:
When calling the function:
No execution error would occur in the program, what's more, everything would be safe.
Nevertheless, ...
Why didn't a segmentation fault occur?
The answer is simple. The base address that the implicit pointer has stored is not being passed
film1
, rather, memory would be reserving for a new type structuretFilm
, that is, the content of the previous memory block is copied to the new memory block. So, we can conclude that both the first and second parameters, what it receives is the base address of the new memory block that has been reserved and this is known as passing by value and as you know, if we repeat this process many times, it will be slow and this is due to the creation of a new object (block or memory region) and above all, to the copy of data that must be sent to the new object to which the first or second parameter of the function will pointfilm_equals
.Recommendation: Always use pass by reference in these cases, this way you send the memory address directly, however, you must be careful not to forget to put the ampersand (
&
) before it.I found your question very interesting. I hope my explanation helps you.
Being declared with asterisks
bool film_equals(tFilm* film1, tFilm* film2);
means that it receivesapuntadores
: memory addresses atFilm*
. With&
it you get the memory address offilm
and oftemporal->e.film
. If you remove the you&
are not passing memory addresses (apuntadores
), but values and that is the reason it thunders.