请问*(char**)a的具体转换过程是怎么样的,请详细点好么?谢谢

时间:2022-03-18 09:21:24
#include <iostream.h>
#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中第一个字符串的首地址。

#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* 型)

#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"
-----------

#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中第一个字符串的首地址。

#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* 型)

#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"
-----------

#6


另外一个问题,请问(char**)a就没有进行任何的类型转换么?

#7


有类型转换啊,void*到char**,这当然叫类型转换,只是这种转换没有数据的变化,和int i = (int)3.14这样的转换不同,这里的转换仅仅是让编译器对一个数值做出不同的解释

#8


呵呵,这道题好亲切哦,是钱能那本书上的吧,这几天偶也在读哦!

#9


强奸式的类型转换

#10


同样的地址,只是看成不同的类型而已。