2

When I do something like:

struct my_struct {
    uint32_t n;
    double   d;
    uint64_t *ptr;
    size_t   val;
};

struct my_struct a;

and in a function:

void a_func(struct my_struct *a) {
    a = (struct my_struct *) [a memory location];
}

I do not get correct values in a;

but when I do something like:

void a_func(struct my_struct *a) {
    *a = *(struct my_struct *) [same memory location];
}

I get correct values in the struct;

Any reasonable explanation for this?

6
  • 1
    Changing a pointer does not change the memory it (used to) point at. Commented Apr 19, 2014 at 12:22
  • please provide compilable examples. Commented Apr 19, 2014 at 12:23
  • Btw: this struct my_struct a { shall be struct my_struct {. Commented Apr 19, 2014 at 12:28
  • If you do this, beware of alignment requirements. You could easily crash your program if your memory isn't aligned. Commented Apr 19, 2014 at 17:04
  • @Cornstalks Can you please give pointer to better understand this problem? #pragma bundling will help? Commented Apr 20, 2014 at 12:02

3 Answers 3

2

Lets look at three different cases:

  1. Change pointer locally

    void foo(S *a) {
        a = p;
    }
    S* b;
    foo(b);
    

    a is a pointer and this function changes the pointer a. It does not change the object a is pointing to. It also does not change b or the object b is pointing to.

  2. Change object pointed to

     void foo(S *a) {
         *a = *p;
     }
     S* b = ...;
     foo(b);
    

    *a = *p performs a deep copy. It copies the object pointed to by p over the object pointed to by a. As b points to the same object as a, b will also see these changes.

  3. Get pointer for usage outside the function

     void foo(S **a) {
         *a = p;
     }
     S* b;
     foo(&b);
    

    Now the function foo accepts a pointer to a pointer. By writing *a = p we change the pointer pointed to by a to p. This can be used to retrieve the pointer p as b will be the same as p after the call to foo.

Sign up to request clarification or add additional context in comments.

Comments

1

I assume you call that function and then try to use the a parameter after the function returned, e.g.

a_func(a);
printf("a->n: %u", a->n);

In both cases, you pass the pointer a by value. Changing the pointer itself in a_func() will not be reflected outside of a_func(). Put another way, a inside of a_func() is a copy of a outside, so changes to the pointer will not reflected outside after returning.

Changing the memory a points to will be visible outside, though.

In the first case (without *), you assign a itself in a_func(). As just explained, the new value of a will be lost as soon as a_func() returns.

In the second case (with *), you copy the memory from [a memory location] the memory pointed to by a. This means, that the memory a points to has to be valid: either it has to be on the stack, or dynamically allocated on the heap. Passing an uninitialized struct my_struct * pointer will lead to crashes sooner or later.

Once you return, you can access the data copied via the a pointer you passed to a_func().

Example for correctly using the copy version (with *) with a local variable a:

struct my_struct a;         // Allocate a my_struct object on the stack.
a_func(&a);                 // Copy data from [some memory location] into a.
printf("a.n: %u", a.n);     // Access and use the newly copied data in a.

Another correct version with a allocated on the heap:

// Allocate a my_struct object on the heap and make a point to that memory.
struct my_struct *a = malloc(sizeof(my_struct)); 
a_func(a);                  // Copy data from [some memory location] into a.
printf("a->n: %u", a->n);   // Access and use the newly copied data in a.
free(a);                    // Take care to free the allocated memory when finished!

A broken example:

struct my_struct *a;        // An uninitialized pointer!
a_func(a);                  // The memory location a points to is overwritten - BUG!
printf("a->n: %u", a->n);   // May still work but you corrupted your memory with
                            // the previous function call. This will lead to crashes!

Comments

0

It's the same as trying to change an integer from 3 to 5 inside a function and then failing. Check the following example:

#include <stdio.h>

void func( int a ) {
    a = 5;
}

int main ( ) {
    int x = 3;
    func( x );
    printf( "%d", x );
    // prints 3 not 5

    return 0;
}

This is because, when you pass x variable into func here, you pass its value, that is 3; func creates a variable named a, assigns it with the passed value 3, assigns it again with the value 5. No change has been made to x there, so x still is just 3.

If you were to pass the address of x as a value to some other function that takes an address as an argument, then access the contents of that address and change it, then you'd be able to remotely change the x, as in the following example:

#include <stdio.h>

void anotherfunc( int * a ) {  // a is an address-holding variable
    *a = 5;  // *a is the content of that address and we are changing it to 5
}

int main ( ) {
    int x = 3;
    func( &x );  // passing the address of the variable x
    printf( "%d", x );
    // prints 5 now

    return 0;
}

Same story for your case, only with one further step of referencing/dereferencing. If you want to make the first version work out, make changes similar to the following:

void a_func(struct my_struct ** a) {  // added an asterisk
    *a = (struct my_struct *) [a memory location];
}

// ...

int main( ) {
    // ...
    struct my_struct * x;
    a_func( &x );

    // ...
    return 0;
}

Here, the a_func takes the address of an address-holding variable (pointer) as an argument, and stores that inside a newly created variable called a, which is a variable that holds address to an address to a struct my_struct. Then it accesses the contents of the address a holds, assigns that with a memory location, and so on...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.