使用指针交换对象

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

void swap(void *a, void *b, size_t size); 

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

 void *temp; temp = a; a = b; b = temp; 

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

同样,只需切换以下值:

 void *temp; *temp = *a; *a = *b; *b = *temp; 

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

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

所以我似乎必须使用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??? 

谢谢!

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

你快到了:

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

memcpy函数复制内存,它是C中对象的定义。(在C ++中称为POD或普通ol’数据,进行比较。)这​​样,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); 

这正是上面函数所做的,因为当你不知道对象的类型时你不能使用赋值,而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); } } 

要回答你的第一个问题,让我们填写一些值来看看发生了什么:

 void* a = 0x00001000; // some memory address void* b = 0x00002000; // another memory address /* Now we'll put in your code */ void* temp; // temp is garbage temp = a; // temp is now 0x00001000 a = b; // a is now 0x00002000 b = temp; // b is now 0x00001000 

所以在这些语句的末尾,指针的值已被交换,也就是说,无论指向的是什么,现在由b指向,反之亦然。 这些指针所指向的是未经修改的,只是现在它们的内存地址由不同的指针保存。

要回答你的第二个问题,你不能取消引用void* 。 原因是void没有大小,因此尝试取消引用或分配给没有大小的东西是荒谬的。 因此, void*是一种保证你可以指向某种东西的方式 ,但是如果没有更多信息(因此你的例行程序的size参数),你永远不会知道那是什么东西

从那里,知道指针和指针所指向的数据的大小,你可以使用像memcpy这样的例程将一个指针指向的数据移动到另一个指向的位置。

参数类似于局部变量,在函数开始执行之前将值复制到它们中。 这个原型:

 void swap(void *a, void *b, size_t size); 

意味着将两个地址复制到名为ab新变量中。 因此,如果您更改ab存储的a ,则在swap返回后,您执行的任何操作都不会产生任何影响。

我的C课程有一个类似的问题。 我认为memcopy可能是最好的,但你也可以试试这个:

  typedef unsigned char * ucp; void swap(void *a, void *b, int size){ ucp c=(ucp)a; ucp d=(ucp)b; for(int i=0; i 

基本上它的作用是将两个指针都转换为unsigned char指针类型。 然后递增指针,在无符号字符的情况下,一次递增一个BYTE。 那么你所做的基本上是在内存中一次复制每个字节的内容。 如果有人想纠正或澄清这一点我也会很感激。

首先,请注意,函数内部指针的任何更改都不会传播到函数外部。 所以你将不得不移动内存。

最简单的方法是使用memcpy – 在堆栈上分配缓冲区,从memcpy分配适当的大小,从ba memcpy ,以及从temp到b最后一个memcpy

如果您正在编写一个函数来交换两个整数,给出指向它们的指针,那么交换指向的值的解决方案将起作用。 但是,考虑一下情况

 struct { int a; int b; } a, b; swap(&a, &b, sizeof(a)); 

您需要找到一种方法来交换传递的每个值的内容,而不知道它们实际包含的内容。

你很亲密

问题是:你只是“交换”指针ab ,它们是函数中的局部变量。

我假设在函数之外你有一些变量,让我们称之为:

 void *x = ...; void *y = ...; 

你打电话的时候:

 swap(x, y, some_size); 

ab分别指向与xy相同的对象。 现在,当你交换ab点时, xy仍然指向他们之前指向的位置。

要更改内存xy点,你必须传递指向x变量的指针,所以指向指针的指针:)

因为您无法更改函数声明,所以您只能交换x (和a )和y (和b )所指向的内存内容。 一些解决方案在其他答案:)通常memcpy是你想要的。

要产生任何实际效果,您需要执行与您提到的第二个块相同的操作:

 void *temp; *temp = *a; *a = *b; *b = *temp; 

这里的问题是’void’没有大小,所以你不能指定’void’。 您需要为temp指定空间,然后使用memcpy()等方法复制值。

要更改内部指针并将其保持在外部,您必须通过引用或双指针传递指针。

如果您的function必须如下:

 void swap(void *a, void *b, size_t size); 

我想你必须实现类似的东西:

 void * temp; temp = malloc(size); memcpy(temp,a,size); memcpy(a,b,size); memcpy(b,temp,size); free(temp); 

我们不需要使用memcpy来交换两个指针,以下代码运行良好(测试交换int *和char *字符串):

 void swap(void **p, void **q) { void *t = *p; *p = *q; *q = t; }