English 中文(简体)
C: Accessing a pointer from outside a function
原标题:

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
", *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
", *(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 ", *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?

最佳回答

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.

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
", *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
", *(evenNums++));
    }
    return 0;
}

You can also take a look at this question from the C-FAQ which deals with your problem also:

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):

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.

问题回答

You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.

int takeEven(int *nums, int numelements, int **newlist) {
    *newlist = malloc(numelements * sizeof *newlist);
    ...
}

...

int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);

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.

You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.

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.

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);

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.





相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签