以下代码无法编译:
void swap(void **p, void **q) {
void *tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void) {
char *s[] = {"help" , "please"};
swap(&s[0], &s[1]);
return 0;
}
虽然这段代码编译并运行得很好:
void swap(void **p, void **q) {
void *tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void) {
char *s[] = {"help" , "please"};
swap((void **) &s[0], (void **) &s[1]);
return 0;
}
为什么需要施法?
答案 0 :(得分:3)
是的,除了已经存在的答案之外,指出void **
与char **
不同:您的代码调用未定义的行为,因为指针不兼容类型。这是你真正想要的:
void swap(void *p1, void *p2, size_t size)
{
unsigned char buf[size];
memcpy(buf, p1, size);
memcpy(p1, p2, size);
memcpy(p2, buf, size);
}
并称之为:
const char *s[] = { "help", "please" }; // also note the use of `const' for string literals
swap(&s[0], &s[1], sizeof(s[0]));
答案 1 :(得分:1)
第一个代码中的指针分配错误不一致。在C类型的字符串文字是char[N]
其中N是字符数。请注意,大多数表达式char[N]
很容易衰减到char*
根据您的声明char *s[] = {"help" , "please"};
,s[i]
的类型为char*
(行为char[N]
已堕入char*
)。
当您通过&s[i]
时,您将传递与char**
不兼容的void**
。第二个代码有效,因为您在函数调用中将其转换为void**
。
void*
可以分配任何地址类型,但必须为void**
分配void*
类型变量的地址。
如果您只有字符串数组,那么在第一版交换函数中,您可以将void
替换为char
,然后您就可以不进行类型转换。
答案 2 :(得分:0)
由于传递函数的内容,该转换使示例编译。
char *var[];
在许多方面与char **var;
话虽如此,您正在向函数传递一个引用/地址数组成员之一(s[0]
)。
另一个更突出的问题是,该函数接受void指针,并传递字符指针(没有转换)。