2

以下代码无法编译:

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;
}

为什么需要铸造?

4

3 回答 3

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]));
于 2013-08-20T17:16:00.517 回答
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*类型变量的地址。

如果您只有字符串数组,那么在交换函数的第一个版本中,voidchar可以在没有类型转换的情况下替换。

于 2013-08-20T17:06:48.373 回答
0

由于您传递函数的内容,转换使示例编译。

char *var[];在很多方面与char **var;

s[0]话虽如此,您正在向函数传递数组 ( )的成员之一的引用/地址。

另一个更突出的问题是该函数接受 void 指针,并传递字符指针(没有强制转换)。

于 2013-08-20T17:06:48.607 回答