[英]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:关于内存管理的一些注意事项:
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).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.