【问题标题】:Swapping 2 string pointers with a function whose parameters are void **用参数为 void 的函数交换 2 个字符串指针 **
【发布时间】:2013-08-20 17:00:30
【问题描述】:

以下代码无法编译:

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

为什么需要强制转换?

【问题讨论】:

  • char **void** 不同。
  • 因为指向void* 的指针与指向任何其他指针类型的指针(如指向char* 的指针)并不通用。 void** 是指向特定类型的指针:void*
  • @WhozCraig 您的一行解释非常好。我意识到我的答案不完整(实际上答案不正确)。

标签: c pointers


【解决方案1】:

是的,除了指出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]));

【讨论】:

  • 我删除了我的答案(我觉得没有正确回答这个问题)。我也觉得你应该解释 WhozCraig 对 OP 的观点。
  • +1 不仅可以查看代码问题,还可以查看 OP 试图解决的问题。我希望我可以再次投票以指出未定义的行为。
  • @WhozCraig 和 Grijesh:谢谢你们!
  • @GrijeshChauhan 您的回答没有错,实际上它可能是 H2C03 在他的开场评论中称为“现有答案”的“答案”。您的第三和第四段基本上就是我的评论内容:指针类型不兼容。取消删除它,我会投票赞成。它也应该在这里。 H2C03 的回答让我们明白了 OP 所尝试的 UB 本质,但您的答案应该在列表中。
  • @GrijeshChauhan 是的,^^ 那。
【解决方案2】:

您在第一个代码中存在不兼容的指针分配错误。在 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,那么您就可以不进行类型转换。

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

    • OP 声明的函数不接受 void 指针;它接受 pointers 到 void 指针。它们相同(尽管实际上可以将指向 void 指针的指针传递给以 void 指针作为参数的函数)。
    • 对,我也尽量不要在指针指针、指针数组和指针数组指针等方面感到困惑......这个列表还在继续......
    猜你喜欢
    • 2016-06-02
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多