开发者

Store pointer value

开发者 https://www.devze.com 2023-02-04 03:58 出处:网络
As I know, when a pointer is passed into a function, it becomes merely a copy of the real pointer. Now, I want the real pointer to be changed without having to return a pointer from a function. For ex

As I know, when a pointer is passed into a function, it becomes merely a copy of the real pointer. Now, I want the real pointer to be changed without having to return a pointer from a function. For example:

int *ptr;

void allocateMemory(int *pointer)
{
     pointer = malloc(sizeof(int));
}

allocateMemory(ptr);

Another thing, which is, how can I allocate memory to 2 or more dimensional arrays? Not by subscript, but by pointer arithmetic. Is this:

int array[2][3];
array[2][1] = 10;

the same as:

int **array;
*(*(array+2)+1) = 10

Also, why do I have to pass in the memory address of a pointer to a function, not the actual pointer itself. For example:

int *a;

why not:

allocateMemory(*a) 

but

allocateMemory(a)

I know I always have to do this, but I really don't understand why. Please explain to me.

The last thing is, in a pointer like this:

int *a;

Is a the address of the memory containing the actual value, or the memory address of the pointer? I always think a is the memory address of the actual value it is pointi开发者_开发技巧ng, but I am not sure about this. By the way, when printing such pointer like this:

printf("Is this address of integer it is pointing to?%p\n",a);
printf("Is this address of the pointer itself?%p\n",&a);


I'll try to tackle these one at a time:

  1. Now, I want the real pointer to be changed without having to return a pointer from a function.

    You need to use one more layer of indirection:

    int *ptr;
    
    void allocateMemory(int **pointer)
    {
        *pointer = malloc(sizeof(int));
    }
    
    allocateMemory(&ptr);
    

    Here is a good explanation from the comp.lang.c FAQ.

  2. Another thing, which is, how can I allocate memory to 2 or more dimensional arrays?

    One allocation for the first dimension, and then a loop of allocations for the other dimension:

    int **x = malloc(sizeof(int *) * 2);
    for (i = 0; i < 2; i++)
        x[i] = malloc(sizeof(int) * 3);
    

    Again, here is link to this exact question from the comp.lang.c FAQ.

  3. Is this:

    int array[2][3];
    array[2][1] = 10;
    

    the same as:

    int **array;
    *(*(array+2)+1) = 10
    

    ABSOLUTELY NOT. Pointers and arrays are different. You can sometimes use them interchangeably, however. Check out these questions from the comp.lang.c FAQ.

  4. Also, why do I have to pass in the memory address of a pointer to a function, not the actual pointer itself?

    why not:

    allocateMemory(*a) 
    

    It's two things - C doesn't have pass-by-reference, except where you implement it yourself by passing pointers, and in this case also because a isn't initialized yet - if you were to dereference it, you would cause undefined behaviour. This problem is a similar case to this one, found in the comp.lang.c FAQ.

  5. int *a;
    

    Is a the address of the memory containing the actual value, or the memory address of the pointer?

    That question doesn't really make sense to me, but I'll try to explain. a (when correctly initialized - your example here is not) is an address (the pointer itself). *a is the object being pointed to - in this case that would be an int.

  6. By the way, when printing such pointer like this:

    printf("Is this address of integer it is pointing to?%p\n",a);
    printf("Is this address of the pointer itself?%p\n",&a);
    

    Correct in both cases.


To answer your first question, you need to pass a pointer to a pointer. (int**)

To answer your second question, you can use that syntax to access a location in an existing array.
However, a nested array (int[][]) is not the same as a pointer to a pointer (int**)

To answer your third question:

Writing a passes the value of the variable a, which is a memory address.
Writing *a passes the value pointed to by the variable, which is an actual value, not a memory address.

If the function takes a pointer, that means it wants an address, not a value.
Therefore, you need to pass a, not *a.
Had a been a pointer to a pointer (int**), you would pass *a, not **a.


Your first question:

you could pass a pointer's address:

void allocateMemory(int **pointer) {
    *pointer = malloc(sizeof(int));
}

int *ptr;
allocateMemory(&ptr);

or you can return a pointer value:

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

int *ptr = mallocateMemory();


I think you're a little confused about what a pointer actually is.
A pointer is just variable whose value represents an address in memory. So when we say that int *p is pointer to an integer, that just means p is a variable that holds a number that is the memory address of an int.
If you want a function to allocate a buffer of integers and change the value in the variable p, that function needs to know where in memory p is stored. So you have to give it a pointer to p (i.e., the memory address of p), which itself is a pointer to an integer, so what the function needs is a pointer to a pointer to an integer (i.e., a memory address where the function should store a number, which in turn is the memory address of the integers the function allocated), so

void allocateIntBuffer(int **pp)
{
    // by doing "*pp = whatever" you're telling the compiler to store
    // "whatever" not in the pp variable but in the memory address that
    // the pp variable is holding.
    *pp = malloc(...);
}

// call it like
int *p;
allocateIntBuffer(&p);

I think the key to your questions is to understand that there is nothing special about pointer variables. A pointer is a variable like any other, only that the value stored in that variable is used to represent a position in memory.


Note that returning a pointer or forcing the caller to move the pointer in an out of a void * temp variable is the only way you can make use of the void * type to allow your function to work with different pointer types. char **, int **, etc. are not convertible to void **. As such, I would advise against what you're trying to do, and instead use the return value for functions that need to update a pointer, unless your function by design only works with a specific type. In particular, simple malloc wrappers that try to change the interface to pass pointer-to-pointer types are inherently broken.

0

精彩评论

暂无评论...
验证码 换一张
取 消