今天来讨论一下C中的内存管理。
记得上周在饭桌上和同事讨论C语言的崛起时,讲到了内存管理方面
我说所有指针使用前都必须初始化,结构体中的成员指针也是一样
有人反驳说,不是吧,以前做二叉树算法时,他的左右孩子指针使用时难道有初始化吗
那时我不知怎么的想不出理由,虽然我还是坚信要初始化的
过了几天这位同事说他试了一下,结构体中的成员指针不经过初始化是可以用(左子树和右子树指针)
那时在忙着整理文档,没在意
今天抽空调了一下,结论是,还是需要初始化的。
而且,不写代码你是不知道原因的(也许是对着电脑久了IQ和记性严重下跌吧)
测试代码如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student{
char *name;
int score;
struct student* next;
}stu,*stu1;
int main(){
stu.name = (char*)malloc(sizeof(char)); /*1.结构体成员指针需要初始化*/
strcpy(stu.name,"Jimy");
stu.score = 99;
stu1 = (struct student*)malloc(sizeof(struct student));/*2.结构体指针需要初始化*/
stu1->name = (char*)malloc(sizeof(char));/*3.结构体指针的成员指针同样需要初始化*/
stu.next = stu1;
strcpy(stu1->name,"Lucy");
stu1->score = 98;
stu1->next = NULL;
printf("name %s, score %d \n ",stu.name, stu.score);
printf("name %s, score %d \n ",stu1->name, stu1->score);
free(stu1);
return 0;
}
写测试代码的过程中我明白了,同事所说的二叉树遍历算法中所用的左子树和右子树指针不需要初始化,其实是这样的,左子树和右子树指向的必须是二叉树节点类型的结构体指针(你填一个长度相同的指针也可以),而该结构体指针是需要初始化的(见注释2),也就是并没有通过malloc来分配内存,
而是将另一个指针的值赋给它
顿时觉得挺无语的,确实,看了很多大学里的教材,对于二叉树的遍历等算法定义的结构体无非是以下形式
struct node{
int data;
struct node* lchild, rchild;
};
使用时都直接的
struct node* root;
root = (struct node*)malloc(sizeof(struct node));
root->data = 3;
struct node* nlchild;
nlchild = (struct node*)malloc(sizeof(struct node));
root->lchild = nlchild;
nlchild->data = 2;
struct node* nrchild;
nlrchild = (struct node*)malloc(sizeof(struct node));
root->rchild = nrchild;
nrchild->data = 4;
这样子给人造成一种错觉好像结构体成员指针是不用初始化的。
可是,只要是指针,要使用它前就必须保证指针变量的值是一个有效的值;否则,它指向的内存一定是垃圾数据!
C语言的内存管理很重要,集魄力和麻烦于一身,看你自己的心态如何了。如果你积极的面对,你正在控制一切;如果你觉得烦躁,你正不得不控制一切。C仍旧是博大精深的语言,信C哥!
/*附加:仍旧是指针*/
stu1 = (struct student*)malloc(sizeof(struct student));/*2.结构体指针需要初始化*/
这一句可能会有人把sizeof里边也填成struct student*
可以理解这样的行为,因为stu本来就是struct student*,可是这样子你就没有为结构体分配足够的内存,使用中会因为内存错误同样报错的。
当然,仅仅为结构体指针分配内存还不够,结构体成员指针仍然需要分配内存,如下
stu1->name = (char*)malloc(sizeof(char));
分享到:
相关推荐
本次实验旨在掌握C语言中数组、结构体和指针的基本用法,以及初步理解链表的概念和操作。实验内容涉及设计一个结构体来存储学生信息,包括学号、姓名、三科成绩和平均成绩。其中,平均成绩需要根据输入的成绩计算...
为实现对原结构体的修改,通常会传递结构体指针: ```c void updateStudent(struct Student *stu) { stu->score += 1.0; } // 调用 updateStudent(&students[0]); ``` 六、结构体嵌套 结构体可以包含其他结构体...
综上所述,结构体指针是C语言中一个非常有用的特性,它允许程序员灵活地操作复合类型数据。正确的使用结构体和指针,能够帮助我们更好地管理内存和创建复杂的数据结构。了解结构体指针及其与宏定义和类型定义的区别...
函数参数中的结构体指针** - **值传递和引用传递**:传递结构体给函数时,可以使用值传递(实际复制整个结构体)或引用传递(传递结构体的地址)。值传递效率较低且不能改变原结构体的值,而引用传递则可以。例如...
在C语言编程中,为了能够灵活地访问这些寄存器,开发者往往需要使用到结构体指针,并且在某些情况下可能还需要对这些指针进行强制类型转换。本文将详细介绍结构体指针的定义、使用方法以及在STM32开发中如何进行强制...
【C语言结构体程序设计】 在C语言中,结构体是一种复合数据类型,它允许我们将不同类型的数据组合在一起形成一个新的数据类型。在这个实验报告中,主要涉及了结构体类型的定义、结构体数组和结构体指针的使用。 1....
在C语言中,结构体(struct)是一种复合数据类型,它允许我们将不同类型的数据组合到一个单一的实体中,便于管理和操作。结构体是C语言中非常重要的一个特性,它为程序设计提供了极大的灵活性。本资料包主要围绕...
结构体是一种构造数据类型,由若干个成员组成,在使用之前必须先定义,然后才能用来定义相应的结构体变量、结构体数组、结构体指针变量。 结构体的定义形式为:struct 结构体名 {成员列表 ;其中各成员都应进行类型...
在 `main` 函数中,我们使用一个指针 `p` 来访问结构体数组的元素,并使用一个循环来遍历整个数组。对于每个元素,我们使用另一个循环来计算学生的总成绩,并将其打印出来。 结构体数组的优点 结构体数组有很多...
如果需要在函数内部修改结构体的成员,需要传递结构体指针。 10. **内存对齐**: 结构体成员在内存中存储时,编译器可能会为了性能优化进行内存对齐。这意味着结构体的实际大小可能大于各成员大小之和。例如,如果...
C语言进阶学习,指针-字符串-结构体-枚举-内存管理
包含链表的建立,插入,删除,查找操作,结构清晰,指针及结构体运用灵活,针对性强,有助于对C语言的深入理解
- **结构体指针**:使用指针操作结构体,包括通过指针访问结构体成员。 - **结构体数组与结构体作为函数参数**:处理结构体数组,以及在函数间传递结构体的方式。 5. **预处理器**: - **宏定义**:理解宏替换的...
【C语言培训 指针 数组 结构体 链表】 C语言是一种强大的、低级别的编程语言,被广泛用于系统开发、嵌入式编程以及各种软件开发中。掌握C语言的关键在于理解和运用指针、数组、结构体和链表等核心概念。 **一、...
在C语言中,我们不能直接在结构体中定义`getArea`这样的成员函数,但可以通过在结构体中包含一个函数指针来实现类似的效果: ```c #include typedef int (*CalcAreaFunc)(struct Rectangle*); struct Rectangle ...
"C语言结构体与共用体" 结构体是一种复杂的数据类型,允许用户自己指定包含多种不同类型的数据项的组合项。结构体类型由用户自己定义,通过struct关键字声明,例如:struct student {int num; char name[20];};这里...
在实验代码中,`struct student *st`就是一个结构体指针,可以用来访问和修改结构体变量的成员。例如,`st->num`用于访问结构体的`num`字段。 3. **链表的概念**: 链表是一种动态数据结构,由一系列节点组成,每...
结构体的声明、定义、初始化和结构体指针的使用是学习的重点。在实际编程中,结构体经常用于实现复杂的数据结构,如图和树。 在课程中,你将学习如何运用这些概念来编写函数,控制程序的流程,比如使用if语句、...
C语言-电费管理系统--可用来学习C语言 1. 可实现基本的增删改查功能,可进行开户功能,即添加用户信息;销户功能即删除用户信息;...如结构体、各种语句、文件、指针等; 7. 此系统可用来学习参考、kechengsheji。
C语言-银行管理系统 ...3. 可实现取款业务 4. 可实现投诉业务功能,录入、查询意见 6. 采用文件操作;可新建文件、读取文件、写入文件;...如结构体、各种语句、文件、指针等; 9. 此系统可用来学习参考、kechengsheji。