c 中的 qsort 类型转换指针
这是在 C 中练习 qsort 函数的简单代码。
int compareF(const void *a, const void *b) {
// return (*(int**)a)[0] - (*(int**)b)[0];
const int *pr1 = *(const int **)a;
const int *pr2 = *(const int **)b;
return pr1[0] - pr2[0];
}
int main() {
int *array[] = {(int[]){2,2,3}, (int[]){1,2,1},(int[]){1,3,3},(int[]){0,2,3},(int[]){1,2,0}};
qsort(array, 5, sizeof(int[3]), compareF);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", array[i][j]);
}
printf("\n");
}
return (0);
}
我不明白第 3 行和第 4 行为什么用指针以这种方式进行类型转换。这是我的理解。首先,无论我们是否设置新变量来保存参数,我们如何使用语法并不重要,因为这两个返回状态是相同的。 其次,它需要进行类型区分,因为参数是 void 类型,因此函数不知道类型。第一个 * 用于解引用参数 a,以便它可以访问地址 a。我们使用 int** 因为..?
main 函数中有一个二维整数数组。根据我的理解,CompareF 函数每次仅将 array[0] 和 array[1] 作为参数。所以我不明白为什么它用两个 ** 键入。
相同的代码只修改了一行代码
int array[3][2]= {{1,4},{3,6},{2,8}};
当以这种方式定义数组时,
const int *pr1 = *(const int[])a;
const int *pr2 = *(const int[])b;
,类型转换是否以相同的方式发生?或者
const int *pr1 = (const int*)a;
const int *pr2 = (const int*)b;
第一种情况不起作用,而第二种情况则有效。但不需要 * 来取消引用吗?喜欢
const int *pr1 = *(const int*)a;
const int *pr2 = *(const int*)b;
This is a simple code to practice qsort function in C.
int compareF(const void *a, const void *b) {
// return (*(int**)a)[0] - (*(int**)b)[0];
const int *pr1 = *(const int **)a;
const int *pr2 = *(const int **)b;
return pr1[0] - pr2[0];
}
int main() {
int *array[] = {(int[]){2,2,3}, (int[]){1,2,1},(int[]){1,3,3},(int[]){0,2,3},(int[]){1,2,0}};
qsort(array, 5, sizeof(int[3]), compareF);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", array[i][j]);
}
printf("\n");
}
return (0);
}
I don't grasp line 3 and 4 of why it is type-casted this way with pointers. This is my understanding. Firstly, it doesn't matter how we use syntax whether we set new variables to save parameters or not like those two return states are just same.
Secondly, it needs to be type cased since parameters are void type so function does not know the type. First * is for dereferencing parameter a so that It has an access to the address a. And we use int** because..?
There's 2d integer array in main function. CompareF function only takes array[0] and array[1] as parameter each time in my understanding. So I don't get why it is typed cased with two **.
Same code with only one line of code modified
int array[3][2]= {{1,4},{3,6},{2,8}};
when array is defined this way, is type casting happened in same way?
const int *pr1 = *(const int[])a;
const int *pr2 = *(const int[])b;
or
const int *pr1 = (const int*)a;
const int *pr2 = (const int*)b;
First case doesn't work and second one does. But doesn't it need * to dereference? like
const int *pr1 = *(const int*)a;
const int *pr2 = *(const int*)b;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
每当要比较任何两个数组元素时,都会调用传递给 qsort 的比较函数,并且它会获取每个数组元素的地址。
您有一个正在排序的
int *
数组,因此每个元素的地址都具有int **
类型。这与compareF
的参数转换为的类型相匹配。取消引用这些指针会得到一个int *
类型的值,这就是数组中实际包含的值。另外,
qsort
的第三个参数不正确。数组元素的类型不是int[2]
,而是int *
类型。如果int
是 4 个字节,而指针是 8 个字节,那么它们恰好是相同的,但您不能依赖于此。The compare function passed to
qsort
is called anytime any two array elements are to be compared, and it is taking the address of each of those array elements.You have an array of
int *
that is being sorted, so the address of each of those elements has typeint **
. That matches the type that the parameters ofcompareF
are casted to. Dereferencing those pointers then gives us a value of typeint *
which is what is actually contained in the array.Also, the third parameter to
qsort
is not correct. The array elements do not have typeint[2]
but instead have typeint *
. If anint
is 4 bytes and a pointer is 8 bytes then they happen to be the same, but you can't depend on that.对于初学者来说,qsort: 的调用
是不正确的。第三个参数是数组元素的大小。由于数组元素的类型为
int *
,因此第三个参数必须为sizeof( int * )
或相同的sizeof( *array )< /code>:
函数
qsort
将指向数组元素的指针作为const void *
类型的指针传递给比较函数compareF
。如果数组的元素类型为
int *
,则指向数组元素的指针的类型为int **
。因此,在函数compareF中,您需要将const void *类型的指针转换为const int **类型。取消引用这样的指针:
您将获得原始数组的一个元素。
由于数组的元素指向类型为
int[3]
的复合文字的第一个元素,因此,例如比较函数中的表达式pr1[0]
给出:复合文字的第一个元素,表达式 pr1[1] 给出复合文字的第二个元素,依此类推。一般来说,使用此 return 语句:
是不正确的,因为所提供的表达式可能会导致有符号整数类型
int
溢出。比较复合文字的所有元素对原始数组的元素(指向复合文字的第一个元素的指针)进行排序更有趣。
这是一个演示程序:
程序输出如下
正如您所看到的,如果两个复合文字的第一个元素彼此相等,则比较第二个元素,依此类推。
如果您有一个像这样声明的二维数组
,则意味着元素类型又是数组类型
int[2]
。因此函数调用将类似于 指向数组元素的指针将具有
int ( * )[2]
类型。因此,在比较函数中取消引用指针,您将获得一个
int[2]
类型的数组(原始数组的一个元素),用作表达式的数组将隐式转换为指向其第一个元素的指针。这是一个演示程序。
程序输出为:
注意,当两个比较元素相等时,比较函数应返回0。相对于函数compareF,这意味着循环之后:
i将等于M,因为比较的一维数组的所有元素都是彼此平等。
For starters this call of qsort:
is incorrect. The third parameter is the size of elements of the array. As the type of elements of the array is
int *
then the third parameter must besizeof( int * )
or that is the samesizeof( *array )
:The function
qsort
passes pointers to elements of the array to the comparison functioncompareF
as pointers of the typeconst void *
.As the elements if the array have the type
int *
then a pointer to an element of the array has the typeint **
.So within the function
compareF
you need to cast the pointers of the typeconst void *
to typesconst int **
. Dereferencing such a pointer like:you will get an element of the original array.
As the elements of the array point to first elements of compound literals that have the type
int[3]
then for example the expressionpr1[0]
within the comparison function gives the first element of a compound literal, the expressionpr1[1]
gives the second element of the compound literal and so on.In general using this return statement:
is incorrect because the supplied expression can produce an overflow for the signed integer type
int
.It is more interesting to sort the elements (pointers to first elements of compound literals) of the original array comparing all elements of compound literals.
Here is a demonstration program:
The program output is
As you can see if first elements of two compound literals are equal each other then second elements are compared and so on.
If you have a two-dimensional array declared like
then it means that the element type is in turn array type
int[2]
. So the function call will look likeAnd pointer to an element of the array will have the type
int ( * )[2]
.So dereferencing the pointer within the comparison function you will get an array of the type
int[2]
(an element of the original array) that that used as an expression is converted implicitly to pointer to its first element.Here is a demonstration program.
The program output is:
Pay attention to that the comparison function shall return 0 when two compared elements are equal each other. Relative to the function
compareF
it means that after the loop:i
will be equal toM
because all elements of the compared one-dimensional arrays are equal each other.