【问题标题】:Pointers and dynamic memory in C and C++C 和 C++ 中的指针和动态内存
【发布时间】:2014-02-14 04:09:37
【问题描述】:

几天前我不得不使用 C,在使用指针时我有点惊讶。

C 中的示例:

#include <stdio.h>
#include <stdlib.h>

void GetPointer(int* p) {
  p = malloc( sizeof(int) );
  if(p) {
    *p = 7;
     printf("IN GetPointer: %d\n",*p);
  } else {
    printf("MALLOC FAILED IN GetPointer\n");
  }
}

void GetPointer2(int* p) {
  if(p) {
    *p = 8;
     printf("IN GetPointer2: %d\n",*p);
  } else {
    printf("INVALID PTR IN GetPointer2");
  }
}

int* GetPointer3(void) {
  int* p = malloc(sizeof(int));
  if(p) {
    *p = 9;
    printf("IN GetPointer3: %d\n",*p);
  } else {
    printf("MALLOC FAILED IN GetPointer3\n");
  }
  return p;
}

int main(int argc, char** argv) {
  (void) argc;
  (void) argv;
  int* ptr = 0;
  GetPointer(ptr);
  if(!ptr) {
    printf("NOPE\n");
  } else {
    printf("NOW *PTR IS: %d\n",*ptr);
    free(ptr);
  }

  int* ptr2 = malloc(sizeof(int));
  GetPointer2(ptr2);
  if(ptr2) {
    printf("NOW *PTR2 IS: %d\n",*ptr2);
    free(ptr2);
  }

  int* ptr3 = GetPointer3();
  if(ptr3) {
    printf("NOW *PTR3 IS: %d\n",*ptr3);
    free(ptr3);
  }
  return 0;
}

输出:

IN GetPointer: 7
NOPE
IN GetPointer2: 8
NOW *PTR2 IS: 8
IN GetPointer3: 9
NOW *PTR3 IS: 9

在此示例中,第一个指针将仅在 GetPointer 方法内具有“值”。为什么在内部使用malloc 只会在方法的生命周期内持续?

我在 C++ 中尝试过这个并得到了相同的行为。我以为它会保留它的价值,但没有。不过,我找到了解决办法:

void GetPointer(int*& p) {
  p = new int;
  if(p) {
    *p = 7;
     printf("IN GetPointer: %d\n",*p);
  } else {
    printf("MALLOC FAILED IN GetPointer\n");
  }
}

在 C 语言中我无法做到这一点。有没有办法在 C 中做同样的事情,或者在尝试给它一个值之前我必须小心并“malloc”指针?

【问题讨论】:

  • 如果要返回分配的内存地址,需要传入int** p。
  • 谢谢大家的cmets!
  • 与 StackOverflow 上的许多 C 问题一样,您应该回归基础。指针是一个。调用函数会将参数的复制到形参声明的变量中。指针是一个,它具有间接运算符* 产生一个变量 的属性。 &amp; 操作符则相反:接受一个变量并产生一个指针值。现在您已经掌握了解释观察到的行为所需的所有事实。一切都遵循这些简单的原则。
  • 不客气。这里要理解的关键是将一个变量赋值给另一个变量会将源变量的值复制到与目标变量关联的存储中。无论赋值是由于赋值运算符还是传递与形式参数对应的参数,这都是正确的。您假设将一个变量分配给另一个使这两个变量共享一个存储空间。您有多个变量都称为p,但它们都引用了不同的存储位置。

标签: c++ c pointers dynamic-memory-allocation


【解决方案1】:

如果要在C 中重新分配指针指向的内容,则必须使用int**,即指向指针的指针。

那是因为指针是按值作为参数复制的,所以如果希望指针指针中所做的更改在函数范围之外可见,则需要另一个级别的间接。

【讨论】:

  • 或者从函数中返回新的指针。我更愿意这样做。
【解决方案2】:

这个

void GetPointer(int* p) {
  p = malloc( sizeof(int) );
  if(p) {
    *p = 7;
     printf("IN GetPointer: %d\n",*p);
  } else {
    printf("MALLOC FAILED IN GetPointer\n");
  }
}

绝对不会造成内存泄漏。

它不做任何事情的原因是您将指针的副本传递给函数(int * p),如果您想更改p指向的内容,则需要传递指针的地址。

void GetPointer(int** p)

【讨论】:

    【解决方案3】:
    void GetPointer(int** pp) {
        int *p = malloc( sizeof(int) );
        if(p) {
            *p = 7;
            printf("IN GetPointer: %d\n",*p);
        } else {
            printf("MALLOC FAILED IN GetPointer\n");
        }
        *pp = p;
    }
    

    【讨论】:

    • 这里 *p = 7 的错误
    • @nikpel7 不,它是有效的。 pint *
    • 我现在看到问题了,pp是指向指针的指针,对不起!
    【解决方案4】:

    在 void GetPointer(int* p) 中,一旦退出功能块,您就会丢失指向动态内存的指针。

    尝试使用指针指向方法:

    GetPointer(int ** p) {
      *p = malloc( sizeof(int) );
      if(*p) {
        **p = 7;
         printf("IN GetPointer: %d\n",**p);
      } else {
        printf("MALLOC FAILED IN GetPointer\n");
      }
    }
    

    【讨论】:

      【解决方案5】:
        p = malloc( sizeof(int) );
      

      malloc( sizeof(int)); 将返回一个指针,然后将其分配给p。但是pGetPointer 本地的,因为指针本身是按值传递给它的。

           +----+
           |    |
        xx +----+  malloc returns this block
      
           +----+
           |    |
        xx +----+  local variable p is assigned this block
      
           +----+
           |  7 |
        xx +----+  p modifies value of this block
      

      函数结束,p 也会结束,留下内存泄漏

           +----+
           |  7 |
        xx +----+  No one points to it anymore
      

      对于GetPointer2GetPointer3,您可以使用malloc

           +----+
           |    |
        yy +----+  malloc returns some other block
      

      【讨论】:

        【解决方案6】:

        对于第一次调用 GetPointer,您需要传入一个指向 int 指针的指针。 (与 C++ 不同,它允许在函数签名中使用 & 运算符进行引用传递,C 总是按值传递内容,这意味着您的代码将 ptrcopy 传递到 @987654322 @函数。)您需要传入该指针的地址(即指针ptr在内存中的位置存储,以便GetPointer方法内的代码可以在该位置放置一些东西,从而修改ptr 本身。

        即电话应该是:

        GetPointer(&ptr);
        

        函数应该是这样的:

        void GetPointer(int** p) {
          *p = malloc( sizeof(int) );
          if(*p) {
            **p = 7;
             printf("IN GetPointer: %d\n",**p);
          } else {
            printf("MALLOC FAILED IN GetPointer\n");
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2012-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-03
          • 2021-02-28
          • 2015-05-19
          • 2013-05-06
          • 1970-01-01
          相关资源
          最近更新 更多