为什么这个指针会出现分段错误 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
确实是指向传递给 qsort
的 int*
数组元素的指针。 **((int **)a)
或简单地 **(int**)a
读取您要比较的整数。
相反,表达式 *((int*)(*(int*)a))
做了一些不同的事情:它从内存中的相同地址读取,但是作为 int
然后假装这个 int
实际上是一个地址并尝试从该地址读取。如果 int
和地址的宽度不同,这将会失败。如果它们恰好大小相同,它将不可移植地成功。
此外,您不能仅通过一个减去另一个来可靠地比较 int
个值。例如 INT_MIN < 1
但 INT_MIN - 1
调用未定义的行为并且很可能计算为 INT_MAX
,一个正值。
intcmp1
应该这样改写:
int intcmp1(const void *v1, const void *v2) { // works better
return (**(int**)v1 > **(int**)v2) - (**(int**)v1 < **(int**)v2);
}
<
和>
比较运算符return1
或0
,因此imtcmp1
将return-1
、0
或 1
。
正如下面的代码,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
确实是指向传递给 qsort
的 int*
数组元素的指针。 **((int **)a)
或简单地 **(int**)a
读取您要比较的整数。
相反,表达式 *((int*)(*(int*)a))
做了一些不同的事情:它从内存中的相同地址读取,但是作为 int
然后假装这个 int
实际上是一个地址并尝试从该地址读取。如果 int
和地址的宽度不同,这将会失败。如果它们恰好大小相同,它将不可移植地成功。
此外,您不能仅通过一个减去另一个来可靠地比较 int
个值。例如 INT_MIN < 1
但 INT_MIN - 1
调用未定义的行为并且很可能计算为 INT_MAX
,一个正值。
intcmp1
应该这样改写:
int intcmp1(const void *v1, const void *v2) { // works better
return (**(int**)v1 > **(int**)v2) - (**(int**)v1 < **(int**)v2);
}
<
和>
比较运算符return1
或0
,因此imtcmp1
将return-1
、0
或 1
。