#include <stdlib.h>
#include <string.h>
int compare(const void* a, const void* b);
char* list[5]={"cattle","car","cabet","cap","canon"};
void main()
{
qsort((void*)list,5,sizeof(list[0]),compare);
for(int i=0; i<5; i++)
cout <<list[i] <<endl;
}
int compare(const void* a, const void* b)
{
return strcmp(*(char**)a, *(char**)b);
}
10 个解决方案
#1
将void*转成char**,再求值,得到char*字符串
#2
这好象是某年软考的题目
#3
首先,const void* a作为一个指针保存的是一个地址,这个地址是 char* list[] 的首地址,也就是字符指针数组的第一个字符指针的地址。
然后 (char**)a 是说,a 是一个指向字符指针的指针,a 的值是一个字符指针的地址,这个字符指针就是 list 的第一个字符指针,这个地址就是 list 的首地址,也就是保存list中的第一个字符串的首地址的指针的地址。
最后,*(char**)a 是对这个地址取引用,按照上面,这个就得到了list中的第一个字符指针,也就是list中第一个字符串的首地址。
然后 (char**)a 是说,a 是一个指向字符指针的指针,a 的值是一个字符指针的地址,这个字符指针就是 list 的第一个字符指针,这个地址就是 list 的首地址,也就是保存list中的第一个字符串的首地址的指针的地址。
最后,*(char**)a 是对这个地址取引用,按照上面,这个就得到了list中的第一个字符指针,也就是list中第一个字符串的首地址。
#4
这是qsort函数的参数是一个函数指针,而qsort的声明:
void qsort( void *base,
size_t num,
size_t width,
int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
compare是自己写得函数,为了通用compare的参数是const void *,而compare中调用strcmp函数,而strcmp的参数是char*型的,
所以在
int compare(const void* a, const void* b)
{
return strcmp(*(char**)a, *(char**)b);
}
中将const void* a转化为指针的指针后在取引用就得到字符串的地址,(a本身为字符串地址的地址,后被强制转换为void* 型)
void qsort( void *base,
size_t num,
size_t width,
int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
compare是自己写得函数,为了通用compare的参数是const void *,而compare中调用strcmp函数,而strcmp的参数是char*型的,
所以在
int compare(const void* a, const void* b)
{
return strcmp(*(char**)a, *(char**)b);
}
中将const void* a转化为指针的指针后在取引用就得到字符串的地址,(a本身为字符串地址的地址,后被强制转换为void* 型)
#5
从数据上看,*(char**)a这样的转化不涉及数据的改变,再怎么转换a的值都是一样的
但是,这样的转换过程是在告诉编译器按照怎样的方式去获得一个数据,是让编译器能够正确解释a这个值的意义
由于我们传入的list是一个指针数组的地址,但在函数compare内部,由于其参数类型为void*,所以a的型别信息已经丢失了
第一步,(char**)a告诉编译器a是一个二级指针,即这个指针指向一个char*型指针,而后者是指向一个字符串
第二步,*(char**)a,解引用后,即获得了(char**)a所指的字符串指针的地址,即最后所得类型为char*,供strcmp调用
理解了这个过程,其实我们想怎么转换都行,例如用下面的也可以
(char*)( * (int*)a )
第一步,* (int*)a 获得a中的数据
第二步,(char*)告诉编译器这个数据是一个字符串指针
一个示意图
list:
char**
-----------
| char* | --------> "cattle"
-----------
| char* | --------> "car"
-----------
但是,这样的转换过程是在告诉编译器按照怎样的方式去获得一个数据,是让编译器能够正确解释a这个值的意义
由于我们传入的list是一个指针数组的地址,但在函数compare内部,由于其参数类型为void*,所以a的型别信息已经丢失了
第一步,(char**)a告诉编译器a是一个二级指针,即这个指针指向一个char*型指针,而后者是指向一个字符串
第二步,*(char**)a,解引用后,即获得了(char**)a所指的字符串指针的地址,即最后所得类型为char*,供strcmp调用
理解了这个过程,其实我们想怎么转换都行,例如用下面的也可以
(char*)( * (int*)a )
第一步,* (int*)a 获得a中的数据
第二步,(char*)告诉编译器这个数据是一个字符串指针
一个示意图
list:
char**
-----------
| char* | --------> "cattle"
-----------
| char* | --------> "car"
-----------
#6
另外一个问题,请问(char**)a就没有进行任何的类型转换么?
#7
有类型转换啊,void*到char**,这当然叫类型转换,只是这种转换没有数据的变化,和int i = (int)3.14这样的转换不同,这里的转换仅仅是让编译器对一个数值做出不同的解释
#8
呵呵,这道题好亲切哦,是钱能那本书上的吧,这几天偶也在读哦!
#9
强奸式的类型转换
#10
同样的地址,只是看成不同的类型而已。
#1
将void*转成char**,再求值,得到char*字符串
#2
这好象是某年软考的题目
#3
首先,const void* a作为一个指针保存的是一个地址,这个地址是 char* list[] 的首地址,也就是字符指针数组的第一个字符指针的地址。
然后 (char**)a 是说,a 是一个指向字符指针的指针,a 的值是一个字符指针的地址,这个字符指针就是 list 的第一个字符指针,这个地址就是 list 的首地址,也就是保存list中的第一个字符串的首地址的指针的地址。
最后,*(char**)a 是对这个地址取引用,按照上面,这个就得到了list中的第一个字符指针,也就是list中第一个字符串的首地址。
然后 (char**)a 是说,a 是一个指向字符指针的指针,a 的值是一个字符指针的地址,这个字符指针就是 list 的第一个字符指针,这个地址就是 list 的首地址,也就是保存list中的第一个字符串的首地址的指针的地址。
最后,*(char**)a 是对这个地址取引用,按照上面,这个就得到了list中的第一个字符指针,也就是list中第一个字符串的首地址。
#4
这是qsort函数的参数是一个函数指针,而qsort的声明:
void qsort( void *base,
size_t num,
size_t width,
int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
compare是自己写得函数,为了通用compare的参数是const void *,而compare中调用strcmp函数,而strcmp的参数是char*型的,
所以在
int compare(const void* a, const void* b)
{
return strcmp(*(char**)a, *(char**)b);
}
中将const void* a转化为指针的指针后在取引用就得到字符串的地址,(a本身为字符串地址的地址,后被强制转换为void* 型)
void qsort( void *base,
size_t num,
size_t width,
int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
compare是自己写得函数,为了通用compare的参数是const void *,而compare中调用strcmp函数,而strcmp的参数是char*型的,
所以在
int compare(const void* a, const void* b)
{
return strcmp(*(char**)a, *(char**)b);
}
中将const void* a转化为指针的指针后在取引用就得到字符串的地址,(a本身为字符串地址的地址,后被强制转换为void* 型)
#5
从数据上看,*(char**)a这样的转化不涉及数据的改变,再怎么转换a的值都是一样的
但是,这样的转换过程是在告诉编译器按照怎样的方式去获得一个数据,是让编译器能够正确解释a这个值的意义
由于我们传入的list是一个指针数组的地址,但在函数compare内部,由于其参数类型为void*,所以a的型别信息已经丢失了
第一步,(char**)a告诉编译器a是一个二级指针,即这个指针指向一个char*型指针,而后者是指向一个字符串
第二步,*(char**)a,解引用后,即获得了(char**)a所指的字符串指针的地址,即最后所得类型为char*,供strcmp调用
理解了这个过程,其实我们想怎么转换都行,例如用下面的也可以
(char*)( * (int*)a )
第一步,* (int*)a 获得a中的数据
第二步,(char*)告诉编译器这个数据是一个字符串指针
一个示意图
list:
char**
-----------
| char* | --------> "cattle"
-----------
| char* | --------> "car"
-----------
但是,这样的转换过程是在告诉编译器按照怎样的方式去获得一个数据,是让编译器能够正确解释a这个值的意义
由于我们传入的list是一个指针数组的地址,但在函数compare内部,由于其参数类型为void*,所以a的型别信息已经丢失了
第一步,(char**)a告诉编译器a是一个二级指针,即这个指针指向一个char*型指针,而后者是指向一个字符串
第二步,*(char**)a,解引用后,即获得了(char**)a所指的字符串指针的地址,即最后所得类型为char*,供strcmp调用
理解了这个过程,其实我们想怎么转换都行,例如用下面的也可以
(char*)( * (int*)a )
第一步,* (int*)a 获得a中的数据
第二步,(char*)告诉编译器这个数据是一个字符串指针
一个示意图
list:
char**
-----------
| char* | --------> "cattle"
-----------
| char* | --------> "car"
-----------
#6
另外一个问题,请问(char**)a就没有进行任何的类型转换么?
#7
有类型转换啊,void*到char**,这当然叫类型转换,只是这种转换没有数据的变化,和int i = (int)3.14这样的转换不同,这里的转换仅仅是让编译器对一个数值做出不同的解释
#8
呵呵,这道题好亲切哦,是钱能那本书上的吧,这几天偶也在读哦!
#9
强奸式的类型转换
#10
同样的地址,只是看成不同的类型而已。