简体   繁体   中英

Pointer to structure NOT changing at all when passed to function

stack.h

 #define MAX_STACK 10
 typedef int STACK_ITEM;
 typedef struct Stack *STACK ;

stack.c

 #include"stack.h"

struct Stack{
    STACK_ITEM contents[MAX_STACK];
    int tos;
};

_Bool create_stack(STACK s){
    s = malloc(sizeof(struct Stack));
    if(s == NULL )
        return 0;
    s->tos = 0;
    return 1;
}

When calling the create_stack function, it doesn't affect s (pointer to structure) at all. So, my question is: why is s not changing, even though it is a pointer, not a value, passed?

Function parameters are its local variables. That is the parameters hold copies of the passed arguments. To change an original argument in a function you have to pass it by reference through pointer.

So change the function like

_Bool create_stack(STACK *s){
    *s = malloc(sizeof(struct Stack));
    if(*s == NULL )
        return 0;
    ( *s )->tos = 0;
    return 1;
}

In order for a C function to modify an argument, the argument must be given as a pointer to the value to be changed. Thus, for a simple integer argument:

void Inc(int *value) {
    ++(*value);
}

will do the trick, but:

void Inc(int value) {
    ++value;
}

will do absolutely nothing to any argument given in a call to Inc , as the function just gets a copy of the 'value' given.

The same goes for a pointer! Your function just changes a copy of the pointer it is passed. So, you should change your function to take a pointer to the pointer:

_Bool create_stack(STACK *s){ // Pointer to a pointer to Stack
    *s = malloc(sizeof(struct Stack)); // Change the value of the STACK object pointed to
    if (*s == NULL )
        return 0;
    (*s)->tos = 0; // And, again, we need to (singly) dereference to 'double' pointer
    return 1;
}

Then, in your calling code, where you originally have something like:

_Bool answer = create_stack(myStackPointer);

you would need to add the address of your pointer:

_Bool answer = create_stack(&myStackPointer);

Feel free to ask for further clarification and/or explanation.

Remember, all parameters are passed by value in C.

When you pass a pointer as a function parameter, you can access the object (or array of objects) pointed to by that pointer.

Your create_stack() is passed a pointer to a struct Stack , that is the s parameter. It then ignores the original value of s and reassigns it. That is allowed, but note that it does not change the original pointer in the caller of create_stack() because function parameters are passed by value .

There are two ways to do what you want.

The first way is to pass a pointer to a pointer:

_Bool create_stack(STACK *s){
    *s = malloc(sizeof(struct Stack));
    if(*s == NULL )
        return 0;
    (*s)->tos = 0;
    return 1;
}

Call it eg:

STACK mystack;
_Bool ret;

ret = create_stack(&mystack);
if (!ret) {
    /* error */
}

The second way is to not pass anything and return a pointer to the allocated stack:

STACK create_stack(void){
    STACK s = malloc(sizeof(struct Stack));
    if(s != NULL ) {
        s->tos = 0;
    }
    return s;
}

Call it eg:

STACK s;

s = create_stack();
if (s == NULL) {
    /* error */
}

Finally, as a point of programming style, do not typedef pointers in the way you have done. It is clearer if the pointer is explicit, for example, use typedef struct Stack STACK; instead of typedef struct Stack *STACK; and adjust the usage accordingly, for example, replacing STACK s with STACK *s and replacing STACK *s with STACK **s .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM