C语言中关于向函数中传入结构指针的易错点及解决方案

前言(Introduction):

最近在学习链表的过程中,我写了这样一段函数:

Recently in the process of learning the linked-list, I wrote a function like this:

/* Add a new item to the list */
int addItem(struct film *head, struct film *prev, char *input){
    /* Request memory to store the input and create a pointer to it */
    struct film *current = (struct film *) malloc(sizeof(struct film));  
    
    /* Judge whether the first node exists */
    if (head==NULL){
        head = current;
    }
    else{
        prev->next = current;
    }

    /* Edit the current node */
    current->next = NULL;
    strcpy(current->title, input);
    puts("[INFO] Please input the rating<0-10> here.");
    scanf("%d",&current->rating);
    while(getchar()!='\n')
        continue;
    
    puts("[INFO] Adding an item successfully.");

    /* set the value of pointer for previous node to the value of current pointer */
    prev = current;

    return 0;
}

很明显,我的目的是为了在链表中添加一个新的节点,并将输入的数据存放进去。

Obviously, I want to add a new node to the linked-list, and save the input to it.

运行整个程序时,我调用该函数能正常完成输入,但是在之后我对链表的所有数据进行遍历输出时,我发现其实数据并没有被存入链表里

Then I ran the whole program, there was nothing wrong with this function. However, when I had a traversal of this list and output all data, I found that nothing is stored in the list.

问题(The Problem): 

那么,问题出在哪里呢?

So, what's the problem?

通过调试,我确认了该函数是正常运行的,所以问题在于函数中的操作并不能正确的完成我想要完成的事情

After debugging, I made sure that the function ran well, so the problem is that my code is unable to do want I want to do correctly.

随后我在该函数被调用结束后,加上了打印当前head的值和prev的值的函数。

Then I add the function to print the value of "head" and "prev" after the function is executed.

两者的结果都是NULL(NULL是我初始化这两个指针变量时所赋的值)。

The results are both NULL, which is what I set to the two pointers when I initial them.

原因(Cause):

我很迷惑,为什么会这样。重新读了几遍代码,都没有发现问题。那就开始单步调试吧。

I am confused, how can that be. Reading the code again and again, I can't find the problem. So I start to debug step by step.

当我看到一切正常运行到函数结束后,"head"的值突然变回NULL时,我恍然大悟。

When I saw the value of "head" changed back to NULL at the moment that all the things ran well and the function is done, the problem suddenly dawned on me.

我将结构的指针传入函数以便改变结构内部的成员变量的值,但是忘了结构指针本身作为被传入的变量,在函数内部是无法改变其值的

(原因是, C语言函数中传入的变量仅是与被调用时传入的参数的值相同的一份拷贝,与原变量处于两个不同的存储空间

In this function, I used the pointer to a struct to change the value of the variable in the struct, but I forgot that the value of the point can't be changed as a variable passed in.

(The reason is that the variable passed in the function is just a copy of the original variable, the memories to store them are different in the C language)

解决方案(Solution):

明确问题之后,修改方案就很容易得出了。

As the problem is clear, it's easy to come up with the solution.

现在我既想改变传入的指针的值,又想能够改变指针指向的成员变量的值,怎么办呢?

Now I want to change the value of the pointer passed in, also want to change the value of the variable in the struct which is pointed by the pointer, how to do that?

二级指针!

The secondary pointer!

所以我修改了代码如下:

So I changed the code as below:

/* Add a new item to the list */
int addItem(struct film **head, struct film **prev, char *input){
    /* Request memory to store the input and create a pointer to it */
    struct film *current = (struct film *) malloc(sizeof(struct film));  
    
    /* Judge whether the first node exists */
    if (*head==NULL){
        *head = current;
    }
    else{
        (*prev)->next = current;
    }

    /* Edit the current node */
    current->next = NULL;
    strcpy(current->title, input);
    puts("[INFO] Please input the rating<0-10> here.");
    scanf("%d",&current->rating);
    while(getchar()!='\n')
        continue;
    
    puts("[INFO] Adding an item successfully.");

    /* set the value of pointer for previous node to the value of current pointer */
    *prev = current;

    return 0;
}

同时将调用该函数时传入的参数改为了指向两个结构的指针的指针。

At the same time, I changed the two parameters to the secondary pointers to the two structs.

运行程序,一切正常。

Run the program, all the things are well.

总结(Conclusion):

回过头来看,这是一个非常简单的问题,但当我在编写和调试这段代码时,始终无法发现问题所在,应了“当局者迷”这句话。当检查代码时,我一直纠结于通过结构指针改变结构体成员变量这一操作,却忽略了结构指针作为参数,本身在传入函数时只是传入了一份与其值相同的拷贝这一问题。所以,当你无法发现你的代码出现了什么问题时,不妨回想一下一些基础概念,也许一切便会豁然开朗。

Looking back on this process, it's a very easy problem, but I can't find that quickly when I am writing and debugging on this code, proving that those closely involved can't see clearly. When checking the code, I focused on the operation that change a variable in the struct through the pointer to the struct, ignoring that the pointer can't be changed as a parameter passed in the function. So, when you can't find what is wrong with your code, why not think back some basic concepts, maybe suddenly you will see the light.

### C语言计算数组元素个数的方法 在C语言中,可以通过`sizeof`运算符来计算数组的元素个数。由于数组中的所有元素类型相同,因此可以利用整个数组占用的字节数除以单个元素占用的字节数来获得数组的元素个数[^1]。 以下是具体的实现方法: #### 使用 `sizeof` 运算符 通过以下公式可以计算数组的元素个数: ```c int num_elements = sizeof(array) / sizeof(array[0]); ``` 其中: - `sizeof(array)` 返回整个数组占用的字节数。 - `sizeof(array[0])` 返回数组第一个元素占用的字节数。 下面是一个完整的代码示例: ```c #include <stdio.h> int main() { int arr[] = {1, 2, 3, 4, 5}; size_t num_elements = sizeof(arr) / sizeof(arr[0]); // 计算数组元素个数 printf("Number of elements in the array: %zu\n", num_elements); return 0; } ``` 运行上述程序会输出: ``` Number of elements in the array: 5 ``` 需要注意的是,这种方法仅适用于已知大小的静态数组。如果数组是指针类型的动态分配数组,则无法使用此方法,因为指针本身并不携带关于其指向的数据长度的信息[^3]。 --- #### 地址连续性验证 为了进一步理解为什么该方法有效,可以从内存布局的角度来看待数组。数组在内存中是以连续的方式存储的,这意味着每个元素之间的地址差正好等于单个元素的字节大小。这种特性使得通过简单的数学运算即可推导出数组的元素数量。 例如,在一个整型数组中,假设每个整数占据4个字节的空间,那么相邻两个元素间的地址差就是4字节。基于这一规律,可以用如下方式验证数组的连续性和元素计数逻辑的一致性。 --- #### 易错提醒 尽管`sizeof`是一种简单有效的工具,但在实际应用中有几个常见的陷阱需要特别注意: 1. **对于函数参数传递的情况**:当数组作为参数传入函数时,它会被退化为指针,此时`sizeof`不再返回原始数组的实际大小。 2. **动态分配数组**:对于通过`malloc`或其他动态分配机制创建的数组,`sizeof`也无法获取其真实大小,因为它本质上只是一个指针。 综上所述,合理运用`sizeof`并结合具体场景能够高效完成数组元素个数的统计工作。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值