すのはら荘春原庄的雪

C语言--结构体总结

2mua·2022-03-25 22:46·338 次阅读

C语言--结构体总结

结构体

一、概念#

  • 在实际问题中,一组数据往往有很多种不同的数据类型。例如,登记学生的信息,可能需要用到char型的姓名,int型或 char型的学号,int型的年龄,char型的性别,float型的成绩。又例如,对于记录一本书,需要 char型的书名,char型的作者名,float型的价格。在这些情况下,使用简单的基本数据类型甚至是数组都是很困难的。而结构体(类似Pascal中的“记录”),则可以有效的解决这个问题。

  • 结构体本质上还是一种数据类型,但它可以包括若干个“成员”,每个成员的类型可以相同也可以不同,也可以是基本数据类型或者又是一个构造类型。

  • 结构体的优点:结构体不仅可以记录不同类型的数据,而且使得数据结构是“高内聚,低耦合”的,更利于程序的阅读理解和移植,而且结构体的存储方式可以提高CPU对内存的访问速度。

二、程序实现#

1.结构体的基本使用#

创建结构体#

  • strcut标识符,用户自定义的名字
  • 结构体不一定只能放外面,main函数里面也可以放。(作用域不同)
  • 定义一个结构体类型,struct Student合起来才算是类型名
  • 成员变量不能直接赋值
Copy
struct Student { char name[50]; int age; int score; };//有分号

命名结构体变量#

  • 类型 +变量
  • struct Student合起来才是类型名
  • s是变量
Copy
struct Student s;

访问成员变量#

  • 如果是普通变量(非指针),使用.运算符
Copy
stpcpy(s.name,"黑马"); s.age = 18; s.score = 100;
  • 如果是指针变量,使用->运算符
Copy
printf("%s %d %d\n",(&s)->name,(&s)->age,(&s)->score);//打印结构体中的值

2.结构体的变量#

  • 普通结构体变量
Copy
//普通结构体变量初始化(此方式需要按照结构体定义顺序赋值) struct Student s = {"abc",10,30}; //打印初始化的值 printf("%s, %d, %d",s.name,s.age,s.score);
  • 结构体数组变量
Copy
//普通结构体变量初始化 struct Student a[] = { {"heibi", 18, 100}, {"testw", 25, 300}, {"eicis", 49, 200}, }; //打印结构体数组个数 int n = sizeof(a)/sizeof(a[0]); printf("n:%d",n); //访问结构体数组内容(4种方式) for(int i = 0; i<n ; ++i) { printf("%s, %d, %d\n",a[i].name,a[i].age,a[i].score); //printf("%s, %d, %d\n",(*(a+i)).name,(*(a+i)).age,(*(a+i)).score); //printf("%s, %d, %d\n",(&a[i])->name,(&a[i])->age,(&a[i])->score); //printf("%s, %d, %d\n",(a+i)->name,(a+i)->age,(a+i)->score); }

3.结构体的嵌套#

  • 引例

    这里可以看到两个结构体得内容相差不大,有三个重复的变量,这种情况即可以使用结构体的嵌套

Copy
struct Info { int age; char sex; char name[50]; }; struct Student { int age; char sex; char name[50]; int score; };
  • 嵌套例子
Copy
struct Info { int age; char sex; char name[50]; }; struct Student { struct Info info;//嵌套另外一个结构体变量 int score; };
  • 初始化及访问
Copy
//结构体嵌套初始化(和不嵌套的结构体一致) struct Student s = {18, 'm', "xiaoming", 18}; //打印嵌套结构体的内容 printf("%d, %c, %s, %d\n",s.info.age, s.info.sex, s.info.name, s.score);
  • 注意事项

    • 嵌套结构体变量,不能是本结构体类型。
    • 但是可以嵌套任何类型的结构体指针变量。
    Copy
    struct Student { struct Info info; int score; //嵌套本结构体类型,会报错。因为`struct Student`类型不确定,内存大小无法确定 // struct Student temp; //嵌套任何类型的结构体指针变量。因为指针大小是确定的。32位系统4字节大小,64位系统8字节大小 struct Student *next; };
  • 补充:typedef的使用:将struct Student结构体重新命名代替为为Student

    • 传统用法
    Copy
    struct Student { int age; char sex; char name[50]; }; typedef struct Student Student;//有分号
    • 常见用法
    Copy
    typedef struct Student { int age; char sex; char name[50]; }Student;

4.同类型结构体相互赋值#

  • 直接赋值
Copy
#include <stdio.h> #include <stdlib.h> #include <string.h> //typedef改一个类型名,把复杂名字改简单点,不能创造新的类型 typedef struct Student { int age; char sex; char name[50]; }Student; int main(void) { Student s1 = {18, 'm', "xiaoming"}; Student s2; // s2 = s1; //同类型的两个变量相互赋值 strcpy(s2.name,s1.name); // 成员变量逐一拷贝 s2.age = s1.age; s2.sex = s1.sex; printf("%d, %c, %s\n",s2.age, s2.sex, s2.name); return 0; }
  • 通过函数实现

    • 关于内存栈区与堆区操作(这里是实现用指针形式访问结构体成员)

      • 如果结构体只定义了一个空指针,便不能操作其内容,要让其指针指向有效地址(栈区或者堆区)
      • 在进行指向栈区空间时,不需要释放,该空间由系统自行维护。
      • 在进行指向堆区空间时,需要自己申请空间,并在使用完成后手动释放。
      Copy
      #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Student { int age; char sex; char name[50]; }Student; int main(void) { //定义一个结构体指针变量 Student *p = NULL; //让指针有个合法指向(指向栈区) // Student temp;//普通结构体变量,栈区 // p = &temp; //让指针有个合法指向(指向堆区) p = (Student *) malloc(sizeof(Student));//申请一个`Student`大小的地址,并用p指向 if(p == NULL) { printf("分配内存失败\n"); return -1; } strcpy(p->name, "小明"); p->sex = 'm'; p->age = 19; printf("%d, %c, %s\n",p->age, p->sex, p->name); //手动释放堆区空间 free(p); p = NULL; return 0; }
    • 函数代码实现赋值

      • 这里使用了const,使s1传入进来的参数不可改变。可防止误改传入参数s1
      Copy
      #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Student { int age; char sex; char name[50]; }Student; //从左往右看,const修饰最近的字符,这修饰的是指针变量 //这里使用了const,使s1所指向的内存(成员变量)不可改变,指针变量可以改变 void fun(const Student *s1, Student *s2) { //两个指针的内容实现赋值 *s2 = *s1; } int main(void) { Student s1; Student s2 = {0,'0',"0"}; printf("%d, %c, %s\n",s2.age, s2.sex, s2.name); strcpy(s1.name, "小明"); s1.sex = 'm'; s1.age = 19; //通过一个函数将s1的值赋值给s2 fun(&s1, &s2); printf("%d, %c, %s\n",s2.age, s2.sex, s2.name); return 0; }

三、内存分析#

  • 通过一个函数,动态分配内存
Copy
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Student { int age; char sex; char name[50]; }Student; //需要注意的是:所有子函数运行完后的变量都会自动进行释放(不能再直接调用) Student* fun() { Student *a; a = (Student *)malloc(sizeof(Student)); return a; } int main(void) { Student *p = NULL; p = fun();//返回并用`p`指向所开辟出来的地址 //只有p指向相应地址时,才能进行赋值 strcpy(p->name, "小明"); p->sex = 'm'; p->age = 19; printf("%d, %c, %s\n", p->age, p->sex, p->name); //释放子函数中`a`开辟出来的空间(`p`和`a`均会指向,只不过`a`在函数调用完后被释放了) free(p); p = NULL; return 0; }

四、出现过的问题#

  1. 不能将x*类型的值分配到x*类型的实体(以下代码会出现该问题)

    Copy
    #include <stdlib.h> //malloc(); #include <stdio.h> typedef struct /*Student*/ //出错原因:在定义结构体时没有定义变量 { //数据域(位置) int x, y; //指针域 struct Point *next; }Student; void main() { Student *pnew = (Student *)malloc(sizeof(Student)); Student *s = NULL; pnew->next = s; //此处会报错:`s为x*类型的值` , pnew->next为`x*类型的实体` }

    解决方法:在定义结构体时加上结构体变量Student即可

posted @   离盏  阅读(338)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
欢迎阅读『C语言--结构体总结』
点击右上角即可分享
微信分享提示
目录