Originally Posted by
c.user
How does qsort knows about a function, how does it call the function, how does you think ?
It calls it, passes arguments to it, and when it calls it, qsort goes to the prototype and makes casts.
OK, let me try this from another angle, because you seem to be confused by how void* works. Yes, object pointers can be converted to and from void*. No, that does not mean that your interpretation of qsort() is right. Here's an analogy.
Code:
#include <stdio.h>
static void f_long(long long a, long long b)
{
printf("%lld %lld\n", a, b);
}
static void f_short(int a, int b)
{
printf("%d %d\n", a, b);
}
static void q(void (*f)(long long, long long))
{
f(15LL, 20LL);
}
int main(void)
{
q(f_long);
q((void(*)(long long, long long))f_short);
return 0;
}
Now, you must agree that an int can be converted to a long long, and will be if f_long() is called such as f_long(15, 20). C does this conversion the way it converts int* to void*; that is, it's legal, and implicit.
Next, the q() function is like qsort(); it takes a pointer to the compare function (which is a simple print function here), and calls it with a couple of arguments, which are long longs that fit into an int. So there's no problem here of representation. Converting 15LL to an int gives you 15.
According to your argument about void*, when f_short() is passed to q(), it will be called correctly because a conversion from long long->int is valid. But in reality, this code is undefined. On four of my five available compilers (gcc, klcc, suncc, clang), the output is a line "15 20" (as it should be), and a line "15 0"--whoops. Only icc printed "15 20" both times. Both results are "correct", because the code is undefined.
you don't using cast l or r (you are use the rule of implicit cast of void to struct car * from standard) y your and matsps words it should not be work for this way
We're not saying that you can't convert between them. We're saying they might be different sizes, or might have different semantics when being passed to a function, etc. That does not preclude a void* from being able to hold a struct car*. An implementation might make void* twice as big as other pointers, so it can store extra information, for example. The conversion to void* is still fine, because void* is definitely large enough to store a smaller size; and the implementation would ensure that conversion back only stores the relevant bits from void* (that is, the non-extra information).