为了比较字符串使用库函数,我学会了编写一个比较函数来比较两个字符串,但我不清楚为什么他们这样做。
int StrCmp(const void *a, const void *b){
char *s1 = *(char**) a;
char *s2 = *(char**) b;
return strcmp(s1,s2);
}
为什么他们必须先把它投给char **? 为什么不直接将它们转换为char *? 喜欢
return strcmp((char*)a, (char*)b);
将(指针)转换为(指向指针的指针)的含义 如果我有
char *x = "string";
如果我为x
进行投射(char**)x; // what is this? Is this character 's'?
我对此非常困惑,谢谢你的澄清 还有一个问题是关于const 如果它是一个常量,我还可以施展它们吗?(我知道我可以这样做)
答案 0 :(得分:4)
该函数的调用者很可能正在使用指针数组,例如:
const char* arr_of_ptr[] =
{
"hello",
"world"
};
在这种情况下,数组的第一个元素是指向char的指针,它本身不是char。因此,StrCmp函数充当指向普通C字符串的指针数组之间的转换器。
但是,它们也会丢弃const关键字,这是不好的做法。该函数应该写成:
int StrCmp(const void *a, const void *b){
const char *s1 = *(const char**) a;
const char *s2 = *(const char**) b;
return strcmp(s1,s2);
}
答案 1 :(得分:4)
“为什么他们必须先将它转换为(字符指针指针)? 为什么不直接将它们转换为(char指针)?“
他们必须把它变成现实。假设价值 你有记忆位置10,000点 像这样的东西:
(char **)
a address a
"points to"
*a **a
mem 1000 mem 10000 mem 20000
to mem 1007 to mem 10007
_____________ _____________ _______________
pointer var --> char pointer -> char
10000 20000 'a'
_____________ _____________ _______________
如果将它转换为(char *),则告诉编译器 a(在这种情况下为10,000)引用的地址是char。 哪个不对。
(char *) address a points
a to
mem 1000 mem 10000 mem 20000
to mem 1007
_____________ ______ ________________
pointer var --> "char" unreachable char
10000 ? 'a'
_____________ ______ ________________
“什么是(指针)指向(指针指针)的意思如果我有
char * x =“string”; 如果我为x做演员
(字符**)X; // 这是什么?这个角色是'?'
此示例中存在的内容类似于:
x *x or x[0] x[1] x[2] x[3] x[4] x[5] x[6]
mem 15000 mem 30000 mem 30001 mem 30002 mem 30003 mem 30004 mem 30005 mem 30006
to 15007
char * char char char char char char char
_________ _________ _________ _________ _________ _________ _________ _________
30000 --> 's' 't' 'r' 'i' 'n' 'g' '\0'
________ _________ _________ _________ _________ _________ _________ _________
如果你告诉编译器x是char **那么它会认为这个 是模式:
x *x or x[0] **x
char *
mem 15000 mem 30000 "char"
to 15007 to 30007
__________ _________ _________
30000 --> "string\0?"
converted to
pointer value -> ??
__________ _________ _________
它错误地最终转到任何“地址”,从30000开始的前8个字节解析为并获得“字符”。但是因为30000是 开始一个以null结尾的字符数组,最好它会进入内存的某个部分并获得一些随机字节,认为它是一个有效的字符。在最坏的情况下,它将获得一个对该程序无效的地址,在尝试访问它时会导致致命错误。
我也可以这样做
return strcmp((char *)a, (char *)b);
不,因为a和b不是char指针。要得到char指针,你无法避免:
return strcmp( *(char**)a, *(char**)b);
使用林登的例子,你会这样打电话:
#include <stdio.h>
#include <string.h>
int StrCmp(const void *a, const void *b){
char *s1 = *(char**) a;
char *s2 = *(char**) b;
printf("s1:%s\n",s1);
printf("s2:%s\n",s2);
return strcmp(s1,s2);
}
const char* arr_of_ptr[] =
{
"hello",
"world"
};
const char **p_arr_of_ptr = arr_of_ptr;
int main(void)
{
const char *cstring1 = "LaDonna";
const char *cstring2 = "McPherson";
const char **pcstring1 = &cstring1;
const char **pcstring2 = &cstring2;
StrCmp(&arr_of_ptr[0],&arr_of_ptr[1]);
StrCmp(pcstring1,pcstring2);
StrCmp(p_arr_of_ptr,p_arr_of_ptr + 1);
}
答案 2 :(得分:1)
这实际上是将一个void指针(即:void*
)转换为指向char的指针(即:char**
)。
请记住,间接/反引用运算符(一元*
运算符)和类型转换运算符(例如:(char**)
)具有相同的优先级,但也具有从右到左的关联性。 / p>
所以,请考虑以下事项:
void myFunction(void* a) {
char* s1; // Pointer to a character, or the beginning of a character array or string
// Note that the effective difference between a character array and a string is that
// a string is a character array that is terminated with the '\0' character
s1 = *(char**) a;
/* The above statement can be decomposed as follows:
* ( *( (char**) a ) )
* 1) Cast the pointer-to-void-type, (ie: void*)'a',
* to a pointer-to-pointer-to-char (ie: char**)
* 2) Deference the value, so it becomes a pointer-to-char
* 3) Assign this char* value to s1
*/
}
这在C中非常常见,你必须做一些漂亮的指针魔术,因为该语言不支持像后继C ++这样的模板。请注意,如果您可以使用高级指针逻辑,那么您可能无需使用C ++代替C语言。
祝你好运!