Just as the follow code,the intcmp1 runs correctly but the intcmp gets a segment fault.I don't know why.These two codes looks as same.
My system environment is: OS X 10.10.2 64bit ; clang
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int intcmp(const void *v1, const void *v2){ //Segment Fault
return (*((int*)(*(int*)v1)) - *((int*)(*(int*)v2)));
}
int intcmp1(const void *v1, const void *v2){ //No Problem
return (**(int**)v1-**(int**)v2);
}
int main(int argc, char *argv[]) {
int a[5]={0,1,2,3,4};
int **b,i;
b=calloc(5,sizeof(int*));
for(i=0;i<5;i++){b[i]=&a[i];}
printf("cmp1 begin\n");
qsort(b,5,sizeof(int*),intcmp1);
printf("cmp1 end\n");
printf("cmp1 begin\n");
qsort(b,5,sizeof(int*),intcmp);
printf("cmp2 end\n");
}
Isn't **((int**)a)
equal as *((int*)(*(int*)a))
?
No, **((int**)a)
and *((int*)(*(int*)a))
are not equivalent. The first one is correct in the context: a
is indeed a pointer to an element of the array of int*
passed to qsort
. **((int **)a)
or simply **(int**)a
reads the integer you want to compare.
Conversely, the expression *((int*)(*(int*)a))
does something different: it reads from the same address in memory, but as an int
and then pretends this int
is actually an address and attempts to read from that address. If int
and addresses don't have the same width, this will fail spectacularly. It they happen to be the same size, it will succeed non portably.
Furthermore, you cannot reliably compare int
values by just subtracting one from the other. For example INT_MIN < 1
but INT_MIN - 1
invokes undefined behaviour and most likely computes to INT_MAX
, a positive value.
intcmp1
should be rewritten this way:
int intcmp1(const void *v1, const void *v2) { // works better
return (**(int**)v1 > **(int**)v2) - (**(int**)v1 < **(int**)v2);
}
The <
and >
comparison operators return 1
or 0
, thus imtcmp1
will return -1
, 0
or 1
precisely.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments