为什么这个指针会出现分段错误 C?

Why this pointer got a Segmentation fault C?

正如下面的代码,intcmp1 运行正确,但 intcmp 得到一个段 fault.I 不知道 why.These 两个代码看起来一样。

我的系统环境是:OS X 10.10.2 64bit ;铿锵声

#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");
}

**((int**)a) 不等于 *((int*)(*(int*)a)) 吗?

不,**((int**)a)*((int*)(*(int*)a)) 不等价。第一个在上下文中是正确的:a 确实是指向传递给 qsortint* 数组元素的指针。 **((int **)a) 或简单地 **(int**)a 读取您要比较的整数。

相反,表达式 *((int*)(*(int*)a)) 做了一些不同的事情:它从内存中的相同地址读取,但是作为 int 然后假装这个 int 实际上是一个地址并尝试从该地址读取。如果 int 和地址的宽度不同,这将会失败。如果它们恰好大小相同,它将不可移植地成功。

此外,您不能仅通过一个减去另一个来可靠地比较 int 个值。例如 INT_MIN < 1INT_MIN - 1 调用未定义的行为并且很可能计算为 INT_MAX,一个正值。

intcmp1应该这样改写:

int intcmp1(const void *v1, const void *v2) { // works better
    return (**(int**)v1 > **(int**)v2) - (**(int**)v1 < **(int**)v2);
}

<>比较运算符return10,因此imtcmp1将return-101