指向结构的指针在传递给函数时根本不改变

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

调用create_stack函数时,根本不会影响s(指向结构的指针)。所以,我的问题是:为什么 s 没有 改变,即使它是一个指针,而不是一个值,通过了?

函数参数是它的局部变量。那就是参数保存传递参数的副本。要更改函数中的原始参数,您必须通过指针按引用传递它。

所以把函数改成

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

为了让 C 函数修改参数,参数必须作为指向要更改的值的指针给出。因此,对于一个简单的整数参数:

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

会成功,但是:

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

绝对不会对调用 Inc 时给出的任何参数做任何事情,因为该函数只是获取给定的 'value' 的副本。

指针也是一样!您的函数只是更改它传递的指针的 copy。因此,您应该更改您的函数以获取指向指针的指针:

_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;
}

然后,在你的调用代码中,你原来有这样的东西:

_Bool answer = create_stack(myStackPointer);

您需要添加指针的地址:

_Bool answer = create_stack(&myStackPointer);

随时要求进一步澄清and/or解释。

记住,在 C 中所有参数都是按值传递的。

当您将指针作为函数参数传递时,您可以访问该指针指向的对象(或对象数组)。

您的 create_stack() 被传递了一个指向 struct Stack 的指针,即 s 参数。然后它 忽略 s 的原始值并重新分配它。这是允许的,但请注意它不会更改 create_stack() 调用者中的原始指针,因为函数参数是按值传递的.

有两种方法可以满足您的需求。

第一种方式是将指针传递给指针:

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

称呼它例如:

STACK mystack;
_Bool ret;

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

第二种方法是不传递任何东西和return指向分配堆栈的指针:

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

称呼它例如:

STACK s;

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

最后,作为编程风格的一点,不要typedef指针在你已经完成的方式中。如果指针是显式的,则更清楚,例如使用 typedef struct Stack STACK; 而不是 typedef struct Stack *STACK; 并相应地调整用法,例如将 STACK s 替换为 STACK *s 并替换 STACK *sSTACK **s.