使用指针交换对象

Cry*_*tal 8 c pointers

我正在尝试交换对象以解决使用void指针交换对象的作业问题.我的功能声明必须是:

void swap(void *a, void *b, size_t size);
Run Code Online (Sandbox Code Playgroud)

我不是在寻找确切的代码如何做到这一点我可以自己解决,但我不确定我是否理解正确.我发现有一个问题是:

void *temp;
temp = a;
a = b;
b = temp;
Run Code Online (Sandbox Code Playgroud)

只更改指针指向的内容.那是对的吗?如果它是正确的,为什么交换指针实际上不会改变*a和*b之间的内容.因为如果你的指针指向不同的东西,你不能取消引用它,现在对象会有所不同吗?

同样,只需切换如下值:

void *temp;
*temp = *a;
*a = *b;
*b = *temp;
Run Code Online (Sandbox Code Playgroud)

也不正确,我不知道为什么.因为在我看来,内容是切换的.

交换对象是否意味着完全交换内存和指针指向的值?

因此我似乎必须使用malloc为我的交换分配足够的空间.如果我为一个对象分配足够的内存,假设它们的大小相同,我真的不知道它与上面的其他两种方法有什么不同.

void *temp = malloc(sizeof(pa));
// check for null pointer
temp = a;
// do something I'm not sure of since I don't quite get how allocating space is any 
// different than the two above methods???
Run Code Online (Sandbox Code Playgroud)

谢谢!

小智 20

交换指针不会更改指向的值.如果确实如此,那就像在信封上交换地址标签,将我带入你的房子,然后你进入我的房子.

你快到了:

void swap(void *a, void *b, size_t size) {
  char temp[size]; // C99, use malloc otherwise
  // char serves as the type for "generic" byte arrays

  memcpy(temp, b,    size);
  memcpy(b,    a,    size);
  memcpy(a,    temp, size);
}
Run Code Online (Sandbox Code Playgroud)

所述的memcpy函数副本存储器,这是在C中的对象的定义(被叫POD或C++纯醇"数据,比较.)以这种方式,memcpy的是你如何做到分配,而无需关心对象的类型,并您甚至可以将其他作业编写为memcpy:

int a = 42, b = 3, temp;

temp = b;
b    = a;
a    = temp;
// same as:
memcpy(&temp, &b,    sizeof a);
memcpy(&b,    &a,    sizeof a);
memcpy(&a,    &temp, sizeof a);
Run Code Online (Sandbox Code Playgroud)

这正是上面函数所做的,因为当你不知道对象的类型时你不能使用赋值,而void是代表"未知"的类型.(当用作函数返回类型时,它也意味着"无".)


作为好奇心,另一个版本在常见情况下避免使用malloc并且不使用C99的VLA:

void swap(void *a, void *b, size_t size) {
  enum { threshold = 100 };
  if (size <= threshold) {
    char temp[threshold];

    memcpy(temp, b,    size);
    memcpy(b,    a,    size);
    memcpy(a,    temp, size);
  }
  else {
    void* temp = malloc(size);
    assert(temp); // better error checking desired in non-example code

    memcpy(temp, b,    size);
    memcpy(b,    a,    size);
    memcpy(a,    temp, size);

    free(temp);
  }
}
Run Code Online (Sandbox Code Playgroud)