I have the following code:
我有以下代码:
int takeEven(int *nums, int numelements, int *newlist) {
newlist = malloc(numelements * sizeof *newlist);
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if (!(*nums % 2)) {
*(newlist++) = *nums;
found++;
}
}
newlist -= found;
printf("First number found %d\n", *newlist); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
The output of the above code:
上述代码的输出:
-1
2088999640
2088857728
If I try printing the first element of the newlist
pointer before returning the function (printf("First number found %d\n", *newlist);
), it works as intended, but why is it that when I try to access the pointer from outside of the function I get those values from seemingly unmalloced addresses?
如果我尝试在返回函数之前打印newlist指针的第一个元素(printf(“第一个数字找到%d\n”,*newlist);),它可以按预期的方式工作,但是为什么当我试图从函数外部访问指针时,我从看似未配置错误的地址中获得这些值呢?
5 个解决方案
#1
3
You need to pass in a pointer to pointer, i.e. int **newlist
. Specifically, newlist is being passed into your function by value, so the newlist in main
and inside your function are two completely different variables.
您需要传递一个指向指针的指针,即int **newlist。具体地说,newlist是按值传递给函数的,所以main和function中的newlist是两个完全不同的变量。
There is also a bug in your test for even numbers:
在你的偶数测试中也有一个错误:
#include <stdio.h>
#include <stdlib.h>
int takeEven(int *nums, int numelements, int **newlist) {
int *list = malloc(numelements * sizeof **newlist);
*newlist = list; // this modifies the value of newlist in main
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if ((*nums % 2) == 0) {
*(list++) = *nums;
found++;
}
}
list -= found;
printf("First number found %d\n", *list); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
You can also take a look at this question from the C-FAQ which deals with your problem also:
你也可以看看C-FAQ里的这个问题,它也处理你的问题:
Q: I have a function which accepts, and is supposed to initialize, a pointer:
问:我有一个函数,它接受并且应该初始化一个指针:
void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
But when I call it like this:
但当我这样称呼它时:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
调用者中的指针保持不变。
A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. In the code above, the called function alters only the passed copy of the pointer. To make it work as you expect, one fix is to pass the address of the pointer (the function ends up accepting a pointer-to-a-pointer; in this case, we're essentially simulating pass by reference):
A:你确定函数初始化了你认为它的功能吗?记住,C中的参数是通过值传递的。在上面的代码中,被调用的函数只修改传递的指针副本。为了让它像您期望的那样工作,一个修复是传递指针的地址(函数最终接受指针对指针的指针;在这种情况下,我们实际上是在模拟通过引用):
void f(ipp)
int **ipp;
{
static int dummy = 5;
*ipp = &dummy;
}
...
int *ip;
f(&ip);
Another solution is to have the function return the pointer:
另一个解决方案是让函数返回指针:
int *f()
{
static int dummy = 5;
return &dummy;
}
...
int *ip = f();
See also questions 4.9 and 4.11.
参见问题4.9和4.11。
#2
6
You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.
您正在按值传递newList指针,因此函数不会修改它。你应该做的。
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof *newlist);
...
}
...
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
#3
2
The newlist you have at the end of the function is not the same as you have when calling the function.
函数末尾的新列表与调用函数时的列表不同。
You are passing a copy of a pointer, then malloc changes that pointer(internal to the function) to point to allocated memory, but the outside one is still unmodified.
您正在传递一个指针的副本,然后malloc将指针(内部的函数)更改为指向分配的内存,但是外部的指针仍然没有被修改。
You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.
您需要使用指向指针的指针作为参数,以便您可以通过双向间接设置ourtside 1点的位置。
int use_pointed_memory(char **pointer){
*pointer = malloc();
}
char *myptr;
use_pointed_memory(&myptr);
So effectively you are giving the function the place where you store the address of what you want and asking the function to store there a valid memory pointer.
实际上,你给了函数一个存放你想要的地址的地方并要求函数在那里存储一个有效的内存指针。
#4
1
You're passing a pointer by value here:
你在这里传递一个指针:
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
Which means that a copy of the pointer is made within that function. You then overwrite that copy:
这意味着在这个函数中创建了一个指针的副本。然后覆盖该副本:
newlist = malloc(numelements * sizeof *newlist);
Since it is but a copy, the caller won't see the result of your assignment. What you seemingly want here is to pass a pointer by reference - for that, you need a pointer to pointer:
因为它只是一个副本,调用者不会看到你的作业的结果。你在这里似乎想要的是通过引用传递一个指针——为此,你需要一个指向指针的指针:
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof **newlist); // apply * to newlist
...
}
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
And don't forget to free
:
不要忘记释放:
free(evenNums);
#5
0
In C, everything is passed by value. So you are passing a copy of evenNums
to the function. Whatever you modify it inside the function doesn't get reflected outside. You need to int**
as the third parameter.
在C中,一切都通过值传递。你将一个偶数的拷贝传递给函数。无论你在函数内部对它进行了什么修改,都不会在外部得到反映。您需要将int**作为第三个参数。
#1
3
You need to pass in a pointer to pointer, i.e. int **newlist
. Specifically, newlist is being passed into your function by value, so the newlist in main
and inside your function are two completely different variables.
您需要传递一个指向指针的指针,即int **newlist。具体地说,newlist是按值传递给函数的,所以main和function中的newlist是两个完全不同的变量。
There is also a bug in your test for even numbers:
在你的偶数测试中也有一个错误:
#include <stdio.h>
#include <stdlib.h>
int takeEven(int *nums, int numelements, int **newlist) {
int *list = malloc(numelements * sizeof **newlist);
*newlist = list; // this modifies the value of newlist in main
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if ((*nums % 2) == 0) {
*(list++) = *nums;
found++;
}
}
list -= found;
printf("First number found %d\n", *list); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
You can also take a look at this question from the C-FAQ which deals with your problem also:
你也可以看看C-FAQ里的这个问题,它也处理你的问题:
Q: I have a function which accepts, and is supposed to initialize, a pointer:
问:我有一个函数,它接受并且应该初始化一个指针:
void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
But when I call it like this:
但当我这样称呼它时:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
调用者中的指针保持不变。
A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. In the code above, the called function alters only the passed copy of the pointer. To make it work as you expect, one fix is to pass the address of the pointer (the function ends up accepting a pointer-to-a-pointer; in this case, we're essentially simulating pass by reference):
A:你确定函数初始化了你认为它的功能吗?记住,C中的参数是通过值传递的。在上面的代码中,被调用的函数只修改传递的指针副本。为了让它像您期望的那样工作,一个修复是传递指针的地址(函数最终接受指针对指针的指针;在这种情况下,我们实际上是在模拟通过引用):
void f(ipp)
int **ipp;
{
static int dummy = 5;
*ipp = &dummy;
}
...
int *ip;
f(&ip);
Another solution is to have the function return the pointer:
另一个解决方案是让函数返回指针:
int *f()
{
static int dummy = 5;
return &dummy;
}
...
int *ip = f();
See also questions 4.9 and 4.11.
参见问题4.9和4.11。
#2
6
You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.
您正在按值传递newList指针,因此函数不会修改它。你应该做的。
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof *newlist);
...
}
...
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
#3
2
The newlist you have at the end of the function is not the same as you have when calling the function.
函数末尾的新列表与调用函数时的列表不同。
You are passing a copy of a pointer, then malloc changes that pointer(internal to the function) to point to allocated memory, but the outside one is still unmodified.
您正在传递一个指针的副本,然后malloc将指针(内部的函数)更改为指向分配的内存,但是外部的指针仍然没有被修改。
You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.
您需要使用指向指针的指针作为参数,以便您可以通过双向间接设置ourtside 1点的位置。
int use_pointed_memory(char **pointer){
*pointer = malloc();
}
char *myptr;
use_pointed_memory(&myptr);
So effectively you are giving the function the place where you store the address of what you want and asking the function to store there a valid memory pointer.
实际上,你给了函数一个存放你想要的地址的地方并要求函数在那里存储一个有效的内存指针。
#4
1
You're passing a pointer by value here:
你在这里传递一个指针:
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
Which means that a copy of the pointer is made within that function. You then overwrite that copy:
这意味着在这个函数中创建了一个指针的副本。然后覆盖该副本:
newlist = malloc(numelements * sizeof *newlist);
Since it is but a copy, the caller won't see the result of your assignment. What you seemingly want here is to pass a pointer by reference - for that, you need a pointer to pointer:
因为它只是一个副本,调用者不会看到你的作业的结果。你在这里似乎想要的是通过引用传递一个指针——为此,你需要一个指向指针的指针:
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof **newlist); // apply * to newlist
...
}
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
And don't forget to free
:
不要忘记释放:
free(evenNums);
#5
0
In C, everything is passed by value. So you are passing a copy of evenNums
to the function. Whatever you modify it inside the function doesn't get reflected outside. You need to int**
as the third parameter.
在C中,一切都通过值传递。你将一个偶数的拷贝传递给函数。无论你在函数内部对它进行了什么修改,都不会在外部得到反映。您需要将int**作为第三个参数。