简体   繁体   English

如何分配内存并将其(通过指针参数)返回给调用函数?

[英]How can I allocate memory and return it (via a pointer-parameter) to the calling function?

I have some code in a couple of different functions that looks something like this:我在几个不同的函数中有一些代码,看起来像这样:

void someFunction (int *data) {
  data = (int *) malloc (sizeof (data));
}

void useData (int *data) {
  printf ("%p", data);
}

int main () {
  int *data = NULL;

  someFunction (data);

  useData (data);

  return 0;
}

someFunction () and useData () are defined in separate modules (*.c files). someFunction ()useData ()在单独的模块(*.c 文件)中定义。

The problem is that, while malloc works fine, and the allocated memory is usable in someFunction , the same memory is not available once the function has returned.问题是,虽然 malloc 工作正常,并且分配的内存可用于someFunction ,但一旦函数返回,相同的内存将不可用。

An example run of the program can be seen here , with output showing the various memory addresses.可以在此处查看程序运行示例,输出显示各种内存地址。

Can someone please explain to me what I am doing wrong here, and how I can get this code to work?有人可以向我解释我在这里做错了什么,以及如何使此代码正常工作?


EDIT: So it seems like I need to use double pointers to do this - how would I go about doing the same thing when I actually need to use double pointers?编辑:所以看起来我需要使用双指针来做到这一点 - 当我真正需要使用双指针时,我将如何做同样的事情? So eg data is所以例如数据是

int **data = NULL; //used for 2D array

Do I then need to use triple pointers in function calls?那么我是否需要在函数调用中使用三重指针?

You want to use a pointer-to-pointer:您想使用指针到指针:

void someFunction (int **data) {
  *data = malloc (sizeof (int));
}

void useData (int *data) {
  printf ("%p", data);
}

int main () {
  int *data = NULL;

  someFunction (&data);

  useData (data);

  return 0;
}

Why?为什么? Well, you want to change your pointer data in the main function.好吧,您想更改主函数中的指针data In C, if you want to change something that's passed in as a parameter (and have that change show up in the caller's version), you have to pass in a pointer to whatever you want to change.在 C 中,如果您想更改作为参数传入的某些内容(并在调用者的版本中显示该更改),则必须传入一个指向您要更改的任何内容的指针。 In this case, that "something you want to change" is a pointer -- so to be able to change that pointer, you have to use a pointer-to-pointer...在这种情况下,“你想改变的东西”是一个指针——所以为了能够改变那个指针,你必须使用一个指向指针的指针......

Note that on top of your main problem, there was another bug in the code: sizeof(data) gives you the number of bytes required to store the pointer (4 bytes on a 32-bit OS or 8 bytes on a 64-bit OS), whereas you really want the number of bytes required to store what the pointer points to (an int , ie 4 bytes on most OSes).请注意,除了您的主要问题之外,代码中还有另一个错误: sizeof(data)为您提供了存储指针所需的字节数(32 位操作系统上为 4 个字节,64 位操作系统上为 8 个字节) ),而您确实想要存储指针指向的内容所需的字节数(一个int ,即大多数操作系统上的 4 个字节)。 Because typically sizeof(int *)>=sizeof(int) , this probably wouldn't have caused a problem, but it's something to be aware of.因为通常sizeof(int *)>=sizeof(int) ,这可能不会引起问题,但需要注意。 I've corrected this in the code above.我已经在上面的代码中更正了这一点。

Here are some useful questions on pointers-to-pointers:这里有一些关于指针指向的有用问题:

How do pointer to pointers work in C? 指向指针的指针如何在 C 中工作?

Uses for multiple levels of pointer dereferences? 用于多级指针取消引用?

A common pitfall especially if you moved form Java to C/C++一个常见的陷阱,尤其是当您从 Java 迁移到 C/C++ 时

Remember when you passing a pointer, it's pass by value ie the value of the pointer is copied.请记住,当您传递指针时,它是按值传递的,即复制指针的值。 It's good for making changes to data pointed by the pointer but any changes to the pointer itself is just local since it a copy!!对指针指向的数据进行更改很有用,但对指针本身的任何更改都只是本地的,因为它是一个副本!!

The trick is to use pass the pointer by reference since you wanna change it ie malloc it etc.诀窍是使用通过引用传递指针,因为您想更改它,即 malloc it 等。

**pointer --> will scare a noobie C programmer ;) **指针 --> 会吓到菜鸟 C 程序员;)

You have to pass a pointer to the pointer if you want to modify the pointer.如果要修改指针,则必须将指针传递给该指针。

ie. IE。 :

void someFunction (int **data) {
  *data = malloc (sizeof (int)*ARRAY_SIZE);
}

edit : Added ARRAY_SIZE, at some point you have to know how many integers you want to allocate.编辑:添加了 ARRAY_SIZE,在某些时候您必须知道要分配多少个整数。

That is because pointer data is passed by value to someFunction .那是因为指针数据是按值传递给someFunction

int *data = NULL;
//data is passed by value here.
someFunction (data); 
//the memory allocated inside someFunction  is not available.

Pointer to pointer or return the allocated pointer would solve the problem.指向指针的指针或返回分配的指针将解决问题。

void someFunction (int **data) {
  *data = (int *) malloc (sizeof (data));
}


int*  someFunction (int *data) {
  data = (int *) malloc (sizeof (data));
return data;
}

someFunction() takes its parameter as int*. someFunction() 将其参数设为 int*。 So when you call it from main(), a copy of the value you passed created.因此,当您从 main() 调用它时,会创建您传递的值的副本。 Whatever you are modifying inside the function is this copy and hence the changes will not be reflected outside.无论您在函数内部修改什么,都是这个副本,因此更改不会反映在外部。 As others suggested, you can use int** to get the changes reflected in data.正如其他人建议的那样,您可以使用 int** 来获取反映在数据中的更改。 Otherway of doing it is to return int* from someFunction().其他方法是从 someFunction() 返回 int*。

Apart from using the doublepointer technique, if there's only 1 return param needed rewrite is as following:除了使用双指针技术,如果只有 1 个返回参数需要重写如下:

 int *someFunction () {
   return (int *) malloc (sizeof (int *));
 }

and use it:并使用它:

 int *data = someFunction ();

Here's the general pattern for allocating memory in a function and returning the pointer via parameter:这是在函数中分配内存并通过参数返回指针的一般模式:

void myAllocator (T **p, size_t count)
{
  *p = malloc(sizeof **p * count);
}
...
void foo(void)
{
  T *p = NULL;
  myAllocator(&p, 100);
  ...
}

Another method is to make the pointer the function's return value (my preferred method):另一种方法是使指针成为函数的返回值(我的首选方法):

T *myAllocator (size_t count)
{
  T *p = malloc(sizeof *p * count);
  return p;
}
...
void foo(void)
{
  T *p = myAllocator(100);
  ...
}

Some notes on memory management:关于内存管理的一些注意事项:

  1. The best way to avoid problems with memory management is to avoid memory management;避免内存管理问题的最好方法是避免内存管理; don't muck with dynamic memory unless you really need it.除非你真的需要它,否则不要乱用动态内存。
  2. Do not cast the result of malloc() unless you're using an implementation that predates the 1989 ANSI standard or you intend to compile the code as C++.不要强制转换 malloc() 的结果,除非您使用的实现早于 1989 ANSI 标准,或者您打算将代码编译为 C++。 If you forget to include stdlib.h or otherwise don't have a prototype for malloc() in scope, casting the return value will supress a valuable compiler diagnostic.如果您忘记包含 stdlib.h 或者在范围内没有 malloc() 的原型,则转换返回值将抑制有价值的编译器诊断。
  3. Use the size of the object being allocated instead of the size of the data type (ie, sizeof *p instead of sizeof (T) );使用被分配对象的大小而不是数据类型的大小(即, sizeof *p而不是sizeof (T) ); this will save you some heartburn if the data type has to change (say from int to long or float to double).如果必须更改数据类型(例如从 int 到 long 或从 float 到 double),这将为您节省一些心痛。 It also makes the code read a little better IMO.它还使代码在 IMO 中读取得更好一些。
  4. Isolate memory management functions behind higher-level allocate and deallocate functions;将内存管理功能隔离在更高级别的分配和解除分配功能之后; these can handle not only allocation but also initialization and errors.这些不仅可以处理分配,还可以处理初始化和错误。

Here you are trying to modifying the pointer ie from "data == Null" to "data == 0xabcd"some other memory you allocated.在这里,您试图将指针从“data == Null”修改为“data == 0xabcd”您分配的其他一些内存。 So to modify data that you need pass the address of data ie &data.所以要修改数据,你需要传递数据的地址,即&data。

void someFunction (int **data) {
  *data = (int *) malloc (sizeof (int));
}

Replying to your additional question you edited in:回复您编辑的其他问题:

'*' denotes a pointer to something. '*' 表示指向某物的指针。 So '**' would be a pointer to a pointer to something, '***' a pointer to a pointer to a pointer to something, etc.所以 '**' 将是一个指向某物的指针的指针,'***' 是一个指向某物的指针的指针,等等。

The usual interpretation of 'int **data' (if data is not a function parameter) would be a pointer to list of int arrays (eg 'int a [100][100]'). 'int **data'(如果数据不是函数参数)的通常解释是指向 int 数组列表的指针(例如,'int a [100][100]')。

So you'd need to first allocate your int arrays (I am using a direct call to malloc() for the sake of simplicity):所以你需要首先分配你的 int 数组(为了简单起见,我使用了对 malloc() 的直接调用):

data = (int**) malloc(arrayCount); //allocate a list of int pointers
for (int i = 0; i < arrayCount; i++) //assign a list of ints to each int pointer
   data [i] = (int*) malloc(arrayElemCount);

Rather than using double pointer we can just allocate a new pointer and just return it, no need to pass double pointer because it is not used anywhere in the function.而不是使用双指针,我们可以只分配一个新指针并返回它,不需要传递双指针,因为它没有在函数的任何地方使用。

Return void * so can be used for any type of allocation.返回void *因此可用于任何类型的分配。

void *someFunction (size_t size) {
    return  malloc (size);
}

and use it as:并将其用作:

int *data = someFunction (sizeof(int));

For simplicity, let me call the above single pointer parameter p and the double pointer pp (pointing to p).为简单起见,让我称上面的单指针参数 p 和双指针 pp(指向 p)。

In a function, the object that p points to can be changed and the change goes out of the function.在一个函数中,p 指向的对象是可以改变的,而这个改变会在函数之外发生。 However, if p itself is changed, the change does not leave the function.但是,如果 p 本身发生更改,则更改不会离开函数。

Unfortunately, malloc by its own nature, typically changes p.不幸的是,malloc 就其本身的性质而言,通常会更改 p。 That is why the original code does not work.这就是原始代码不起作用的原因。 The correction (58) uses the pointer pp pointing to p.修正 (58) 使用指向 p 的指针 pp。 in the corrected function, p is changed but pp is not.在更正后的函数中,p 发生了变化,但 pp 没有发生变化。 Thus it worked.因此它起作用了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何分配内存,分配值并将其返回给调用函数? - How do I allocate memory, assign values, and return it to the calling function? 我想将 memory 分配给 function 指针 - I want to allocate memory to function pointer 当写一个返回指针的 function 时,为什么要分配 memory 给我要返回的指针? - When writing a function that returns pointer, why should I allocate memory to the pointer I'm going to return? 我可以使用自己的内存分配char指针吗? - Can I allocate a char pointer with own memory? 我在函数中分配内存,并返回char *,我应该如何释放它? - I allocate memory in function, and return char*, how should I free it? 如何在C函数中为结构指针分配内存 - How to allocate memory to a struct pointer in a function in c 如何为传递给函数的指针分配内存? - How to allocate memory to an pointer passed to a function? 如何在C函数中分配三重指针的内存 - How to allocate memory of triple pointer in a C function 如何在函数中分配双指针的内存? - How to allocate memory of a double pointer in a function? 如何为函数中的结构正确分配内存以返回其值以供以后使用以及如何将结构转换为指针? - How to correctly allocate memory for a structure in a function to return its value for later use and how to cast a structure into a pointer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM