c中的qsort类型转换指针
qsort type casting pointers in c
这是一个简单的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 行为何使用指针以这种方式进行类型转换。这是我的理解。首先,无论我们是否设置新变量来保存参数,我们如何使用语法都没有关系,就像这两个 return 状态一样。
其次,它需要区分类型,因为参数是 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;
传递给 qsort
的比较函数在要比较任何两个数组元素的任何时候调用,它获取每个数组元素的地址。
您有一个正在排序的 int *
数组,因此每个元素的地址都具有类型 int **
。这与 compareF
的参数转换为的类型相匹配。取消引用这些指针然后给我们一个 int *
类型的值,这就是数组中实际包含的值。
此外,qsort
的第三个参数不正确。数组元素的类型不是 int[2]
,而是类型 int *
。如果 int
是 4 个字节,而指针是 8 个字节,那么它们恰好是相同的,但你不能依赖它。
对于初学者来说,这个 qsort 调用:
qsort(array, 5, sizeof(int[2]), compareF);
不正确。第三个参数是数组元素的大小。由于数组元素的类型是 int *
那么第三个参数必须是 sizeof( int * )
或者是相同的 sizeof( *array )
:
qsort(array, 5, sizeof( *array ), compareF);
函数qsort
将指向数组元素的指针作为const void *
.
类型的指针传递给比较函数compareF
作为元素,如果数组的类型为 int *
,则指向数组元素的指针的类型为 int **
。
因此在函数 compareF
中,您需要将类型 const void *
的指针转换为类型 const int **
。取消引用这样的指针:
const int *pr1 = *(const int **)a;
你会得到原始数组的一个元素。
由于数组的元素指向具有类型 int[3]
的复合文字的第一个元素,因此例如比较函数中的表达式 pr1[0]
给出了复合文字的第一个元素,表达式 pr1[1]
给出复合文字的第二个元素,依此类推。
通常使用此 return 语句:
return pr1[0] - pr2[0];
是不正确的,因为提供的表达式可能会导致带符号整数类型 int
的溢出。
比较复合文字的所有元素,对原始数组的元素(指向复合文字的第一个元素的指针)进行排序更有趣。
这里有一个演示程序:
#include <stdio.h>
#include <stdlib.h>
enum { M = 3 };
int compareF( const void *a, const void *b )
{
const int *pr1 = *( const int ** )a;
const int *pr2 = *( const int ** )b;
size_t i = 0;
while ( i != M && pr1[i] == pr2[i] ) ++i;
return i == M ? 0 : ( pr2[i] < pr1[i] ) - ( pr1[i] < pr2[i] );
}
int main(void)
{
int * array[] =
{
(int[M]){2,2,3},
(int[M]){1,2,1},
(int[M]){1,3,3},
(int[M]){0,2,3},
(int[M]){1,2,0}
};
const size_t N = sizeof( array ) / sizeof( *array );
qsort( array, N, sizeof( *array ), compareF );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < M; j++ )
{
printf( "%d ", array[i][j] );
}
putchar( '\n' );
}
}
程序输出为
0 2 3
1 2 0
1 2 1
1 3 3
2 2 3
如您所见,如果两个复合文字的第一个元素彼此相等,则比较第二个元素,依此类推。
如果你有一个 two-dimensional 数组声明为
int array[3][2]= {{1,4},{3,6},{2,8}};
那么表示元素类型又是数组类型int[2]
。所以函数调用看起来像
qsort(array, sizeof( array ) / sizeof( *array ), sizeof( int[2] ), compareF);
并且指向数组元素的指针的类型为 int ( * )[2]
。
因此,在比较函数中取消引用指针,您将得到一个 int[2]
类型的数组(原始数组的一个元素),用作表达式的数组被隐式转换为指向其第一个元素的指针。
这里有一个演示程序。
#include <stdio.h>
#include <stdlib.h>
enum { M = 2 };
int compareF( const void *a, const void *b )
{
const int *pr1 = *( const int ( * )[M] )a;
const int *pr2 = *( const int ( * )[M] )b;
size_t i = 0;
while ( i != M && pr1[i] == pr2[i] ) ++i;
return i == M ? 0 : ( pr2[i] < pr1[i] ) - ( pr1[i] < pr2[i] );
}
int main(void)
{
int array[][M] =
{
{ 1, 4 }, { 3, 6 }, { 2, 8 }
};
const size_t N = sizeof( array ) / sizeof( *array );
qsort( array, N, sizeof( *array ), compareF );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < M; j++ )
{
printf( "%d ", array[i][j] );
}
putchar( '\n' );
}
}
程序输出为:
1 4
2 8
3 6
注意当两个比较元素相等时,比较函数应return0。相对于函数compareF
表示循环后:
size_t i = 0;
while ( i != M && pr1[i] == pr2[i] ) ++i;
i
将等于 M
因为比较的 one-dimensional 数组的所有元素彼此相等。
这是一个简单的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 行为何使用指针以这种方式进行类型转换。这是我的理解。首先,无论我们是否设置新变量来保存参数,我们如何使用语法都没有关系,就像这两个 return 状态一样。 其次,它需要区分类型,因为参数是 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;
传递给 qsort
的比较函数在要比较任何两个数组元素的任何时候调用,它获取每个数组元素的地址。
您有一个正在排序的 int *
数组,因此每个元素的地址都具有类型 int **
。这与 compareF
的参数转换为的类型相匹配。取消引用这些指针然后给我们一个 int *
类型的值,这就是数组中实际包含的值。
此外,qsort
的第三个参数不正确。数组元素的类型不是 int[2]
,而是类型 int *
。如果 int
是 4 个字节,而指针是 8 个字节,那么它们恰好是相同的,但你不能依赖它。
对于初学者来说,这个 qsort 调用:
qsort(array, 5, sizeof(int[2]), compareF);
不正确。第三个参数是数组元素的大小。由于数组元素的类型是 int *
那么第三个参数必须是 sizeof( int * )
或者是相同的 sizeof( *array )
:
qsort(array, 5, sizeof( *array ), compareF);
函数qsort
将指向数组元素的指针作为const void *
.
compareF
作为元素,如果数组的类型为 int *
,则指向数组元素的指针的类型为 int **
。
因此在函数 compareF
中,您需要将类型 const void *
的指针转换为类型 const int **
。取消引用这样的指针:
const int *pr1 = *(const int **)a;
你会得到原始数组的一个元素。
由于数组的元素指向具有类型 int[3]
的复合文字的第一个元素,因此例如比较函数中的表达式 pr1[0]
给出了复合文字的第一个元素,表达式 pr1[1]
给出复合文字的第二个元素,依此类推。
通常使用此 return 语句:
return pr1[0] - pr2[0];
是不正确的,因为提供的表达式可能会导致带符号整数类型 int
的溢出。
比较复合文字的所有元素,对原始数组的元素(指向复合文字的第一个元素的指针)进行排序更有趣。
这里有一个演示程序:
#include <stdio.h>
#include <stdlib.h>
enum { M = 3 };
int compareF( const void *a, const void *b )
{
const int *pr1 = *( const int ** )a;
const int *pr2 = *( const int ** )b;
size_t i = 0;
while ( i != M && pr1[i] == pr2[i] ) ++i;
return i == M ? 0 : ( pr2[i] < pr1[i] ) - ( pr1[i] < pr2[i] );
}
int main(void)
{
int * array[] =
{
(int[M]){2,2,3},
(int[M]){1,2,1},
(int[M]){1,3,3},
(int[M]){0,2,3},
(int[M]){1,2,0}
};
const size_t N = sizeof( array ) / sizeof( *array );
qsort( array, N, sizeof( *array ), compareF );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < M; j++ )
{
printf( "%d ", array[i][j] );
}
putchar( '\n' );
}
}
程序输出为
0 2 3
1 2 0
1 2 1
1 3 3
2 2 3
如您所见,如果两个复合文字的第一个元素彼此相等,则比较第二个元素,依此类推。
如果你有一个 two-dimensional 数组声明为
int array[3][2]= {{1,4},{3,6},{2,8}};
那么表示元素类型又是数组类型int[2]
。所以函数调用看起来像
qsort(array, sizeof( array ) / sizeof( *array ), sizeof( int[2] ), compareF);
并且指向数组元素的指针的类型为 int ( * )[2]
。
因此,在比较函数中取消引用指针,您将得到一个 int[2]
类型的数组(原始数组的一个元素),用作表达式的数组被隐式转换为指向其第一个元素的指针。
这里有一个演示程序。
#include <stdio.h>
#include <stdlib.h>
enum { M = 2 };
int compareF( const void *a, const void *b )
{
const int *pr1 = *( const int ( * )[M] )a;
const int *pr2 = *( const int ( * )[M] )b;
size_t i = 0;
while ( i != M && pr1[i] == pr2[i] ) ++i;
return i == M ? 0 : ( pr2[i] < pr1[i] ) - ( pr1[i] < pr2[i] );
}
int main(void)
{
int array[][M] =
{
{ 1, 4 }, { 3, 6 }, { 2, 8 }
};
const size_t N = sizeof( array ) / sizeof( *array );
qsort( array, N, sizeof( *array ), compareF );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < M; j++ )
{
printf( "%d ", array[i][j] );
}
putchar( '\n' );
}
}
程序输出为:
1 4
2 8
3 6
注意当两个比较元素相等时,比较函数应return0。相对于函数compareF
表示循环后:
size_t i = 0;
while ( i != M && pr1[i] == pr2[i] ) ++i;
i
将等于 M
因为比较的 one-dimensional 数组的所有元素彼此相等。