Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用指针交换对象_C_Pointers - Fatal编程技术网

C 使用指针交换对象

C 使用指针交换对象,c,pointers,C,Pointers,我试图用一个家庭作业问题来交换对象,这个问题使用空指针来交换对象。我的职能声明必须是: void swap(void *a, void *b, size_t size); 我并不是在寻找确切的代码来完成它,所以我可以自己找出它,但我不确定我是否理解正确。我发现一个问题是: void *temp; temp = a; a = b; b = temp; 只更改指针指向的内容。对吗?如果它是正确的,为什么交换指针实际上不改变*a和*b之间的内容呢。因为如果你的指针指向不同的东西,你不能取消它的引用

我试图用一个家庭作业问题来交换对象,这个问题使用空指针来交换对象。我的职能声明必须是:

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);
我认为您必须实现以下内容:

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

交换指针不会更改指向的值。如果是这样的话,那就好比交换信封上的地址标签,把我搬进你家,把你搬进我家

你就快到了:

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);
}
函数复制内存,这是C中对象的定义(称为POD或PAND OL数据在C++中比较)。这样,MimcPy就是如何在不关心对象类型的情况下完成分配,甚至可以编写其他任务作为MimcPy,而不是:

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 swap(void*a、void*b、size\u t size){
枚举{阈值=100};

如果(size首先,请注意,对函数内部指针的任何更改都不会传播到函数外部。因此,您必须移动内存


最简单的方法是使用
memcpy
-在堆栈上分配一个缓冲区,
memcpy
a
放入适当大小的缓冲区,
memcpy
b
a
,最后一个
memcpy
从temp进入
b
要产生任何实际效果,您需要执行以下操作你提到的第二个街区:

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

这里的问题是“void”没有大小,因此您无法按原样分配“void”。您需要为要指向的
temp
分配空间,然后使用类似
memcpy()的方法复制值

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

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

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

如果您正在编写一个函数来交换两个整数,给定指向它们的指针,那么您的swa解决方案将不会产生任何影响将指向的值进行工作,但是,考虑到

的情况。
struct {
  int a;
  int b;
} a, b;

swap(&a, &b, sizeof(a));

您需要找出一种方法来交换传递的每个值的内容,而不知道它们实际上是由什么组成的。

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

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
因此,在这些语句的末尾,指针的值被交换,也就是说,无论
a
指向什么,现在都被
b
指向,反之亦然。这些指针指向的值没有被修改,只是现在它们的内存地址被不同的指针持有

要回答第二个问题,您不能取消引用
void*
。原因是
void
没有大小,因此尝试取消引用或分配给没有大小的对象是毫无意义的。因此,
void*
是一种保证您可以指向某个对象的方法,但您永远不会知道该对象是什么不需要更多信息(因此将
size
参数添加到例程中)

从那里,知道指针和指针指向的数据的大小,您可以使用类似于
memcpy
的例程将一个指针指向的数据移动到另一个指针指向的位置。

您已经接近了

问题是:只“交换”函数中的局部变量指针a和b

我假设函数之外有一些变量,我们调用它们:

void *x = ...;
void *y = ...;
当你打电话时:

swap(x, y, some_size);
a和b分别指向与x和y相同的对象。现在,当您交换a和b点时,x和y仍然指向它们之前指向的对象

要更改内存x和y的指向,必须将指针传递给x变量,因此指针指向:)


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

对于我的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<size; i++){
        int temp=(int)c[i];
    c[i]=(int)d[i];
    d[i]=temp;
      }

    }
typedef无符号字符*ucp;
无效交换(无效*a、无效*b、整数大小){
ucp c=(ucp)a;
ucp d=(ucp)b;

对于(int i=0;i我们不需要使用memcpy来交换两个指针,下面的代码工作得很好(经过测试用于交换int*和char*字符串):

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