文章目录:

一: 结构体定义的3种方式

1.第一种方式 先声明结构体,再定义变量名

2.第二种方式 声明类型的同时定义变量

3.第三种方式 直接定义结构体类型变量

二: 访问结构体中的成员

三: 结构体数组

1.语法形式

2.初始化

四:指向结构体类型数据的指针

1.指向结构体类型数据的指针

1.1 概念性质

1.2 语法一般形式

1.3 访问的一般形式

2.结构体指针变量作为函数参数

2.1 案例一:(先用结构体变量作函数参数)

2.2 案例二:(改用指向结构体变量(或数组)的指针作实参)

2.3 用结构体变量的成员作参数

3.指向结构体数组的指针

五:用指针处理链表

1.链表概述

2.简单链表例子

3.建立动态链表

3.1 打印链表

3.2 删除节点

3.3 更新节点

3.4 增加节点

五:几个结构体中常用的函数memcpy() memset() bzero()

1.结构体的复制函数memcpy

2.内存空间赋值函数memset

3.内存空间清零函数bzero


C语言——结构体&位域

main(){struct bs{unsigned a:1;unsigned b:3;unsigned c:4;} bit,*pbit;bit.a=1;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */bit.b=7;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */bit.c=15;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */printf("%d,%d,%d\n",bit.a,bit.b,bit.c);    /* 以整型量格式输出三个域的内容 */pbit=&bit;    /* 把位域变量 bit 的地址送给指针变量 pbit */pbit->a=0;    /* 用指针方式给位域 a 重新赋值,赋为 0 */pbit->b&=3;    /* 使用了复合的位运算符 "&=",相当于:pbit->b=pbit->b&3,位域 b 中原有值为 7,与 3 作按位与运算的结果为 3(111&011=011,十进制值为 3) */pbit->c|=1;    /* 使用了复合位运算符"|=",相当于:pbit->c=pbit->c|1,其结果为 15 */printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);    /* 用指针方式输出了这三个域的值 */
}

一: 结构体定义的3种方式

对于结构体变量的成员可以像普通变量一样进行各种运算student2.score = student1.score;sum = student1.score + student2.score;student1.age ++;++ student1.age;可以引用结构体变量【成员】的地址,也可以引用结构体【变量】的地址scanf("%d", &student1.num);    // 输入 student1.num 的值printf("%o", &student1);       // 输出 student1 的首地址但不能用以下语句整体读入结构体变量如:scanf("%d,%s,%c,%d,%f,%s", &student1);

1.第一种方式 先声明结构体,再定义变量名

// 第一种方式 先声明结构体,再定义变量名
struct Student
{int age;float score;char sex;
};
struct Student st2;

2.第二种方式 声明类型的同时定义变量

// 第二种方式 声明类型的同时定义变量
struct Student2
{int age;float score;char sex;
} st2;

3.第三种方式 直接定义结构体类型变量

// 第三种方式 直接定义结构体类型变量
struct
{int age;float score;char sex;
} st3;

二: 访问结构体中的成员

如何取出结构体变量中的每一个成员【重点】:结构体变量名.成员名指针变量名->成员名 (第二种方式更常用)
其中指针变量名->成员名 在计算机内部会被转化成 (*指针变量名).成员名 的方式来执行。所以说这两种方式是等价的struct Student st = {80, 66.6, 'F'};  // 初始化  定义的同时赋初值struct Student * pst = &st;       // &st不能改成stpst->age = 88;     // 第二种方式st.score = 66.6f;  // 第一种方式 

三: 结构体数组

#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct person
{char name[20];int count;}leader[3] = {{"Li", 0},{"Zhang", 0},{"Fun", 0}};void main()
{int i, j;char leader_name[20];for(i = 1; i<= 10;i++){scanf("%s", leader_name);for(j=0;j<3;j++)if(strcmp(leader_name, leader[j].name) == 0)leader[j].count ++;}printf("\n");for(i=0;i<3;i++)printf("%5s: %d\n", leader[i].name, leader[i].count);system("pause");
}

1.语法形式

    struct student{int num;char name[20];char sex;int age;float score;char addr[30];};struct student student[3];也可以这样:struct student{int num;char name[20];char sex;int age;float score;char addr[30];}student[3];

2.初始化

    struct student{int num;  …};struct student str[]{{…},{…},{…}};也可以这样:struct student{int num;char name[20]; char sex;     int age; float score; char addr[30];}stu[2]= {{101,″LiLin″,′M′,18,87.5,″Beijing″},        {102,″Zhang″,′F′,19,99,″Shanghai″}};

四:指向结构体类型数据的指针

1.指向结构体类型数据的指针

1.1 概念性质

    一个结构体变量的指针就是该结构体变量所占据的内存段的起始地址设置一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址

1.2 语法一般形式

    struct 结构名 *结构指针变量名struct stu *pstu;    //stu表示结构 pstu表示指针名称 *pstu表示指针结构指针变量必须先赋值后才能使用赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量例如struct student *pstu;struct student{int num;char name[20];char sex;int age;float score;char addr[30]} boy;pstu =&boy;//正确的     pstu=&student错误表示

1.3 访问的一般形式

  (*结构指针变量).成员名        结构指针变量->成员名例如:(*pstu).num  //学生的学号pstu->num    //学生的学号
#include <stdio.h>
struct stu{int num;char *name;char sex;float score;
}boy1 = {101,"yujunwen",'M',60}void main(){struct stu *pstu;pstu=&boy1;printf("学号为%d 姓名为%s",boy1.num,boy1.name);printf("学号为%d 姓名为%s",(*pstu).num,(*pstu).name);printf("学号为%d 姓名为%s",pstu->num,pstu->name);
}

2.结构体指针变量作为函数参数

将一个结构体变量的值传递给另一个函数,主要形式:用结构体变量的成员作参数【变量】用结构体变量作实参【变量指针】用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址穿给形参

2.1 案例一:(先用结构体变量作函数参数)

#include <stdio.h>
#include <string.h>
struct student{int num;char name[20];float score[3];
};
void print(struct student)
void main(){struct student stu;stu.num = 8;//下面的yujunwen出现在常量区,对应上面的char name[20]出现在栈中strpy(stu.name,"yujunwen");//stu.name ="yujunwen";//如果使用上面注释中的方式,需要改为char *name.将常量区的yujunwen的地址交给name 指针stu.score[0] = 98.5;stu.score[1] = 99.0;stu.score[2] = 99.5;print(stu);
}
void printf(struct student stu){
printf("学号为%d",stu.num);
printf("姓名为%d",stu.name);
printf("语文为%d",stu.score[0]);
printf("数学为%d",stu.score[1]);
}

2.2 案例二:(改用指向结构体变量(或数组)的指针作实参)

#include <stdio.h>
#include <string.h>
struct student{int num;char name[20];float score[3];
};void print(struct student *);
void main(){struct student stu;stu.num = 8;strpy(stu.name,"yujunwen");stu.score[0] = 98.5;stu.score[1] = 99.0;stu.score[2] = 99.5;print(&stu);
}
void printf(struct student *p){
printf("学号为%d",p->num);
printf("姓名为%d",p->name);
printf("语文为%d",p->score[0]);
printf("数学为%d",p->score[1]);
}

2.3 用结构体变量的成员作参数

例如:用 stu[1].num 或 stu[2].name 作函数实参,将实参值传给形参
用法和用普通变量作实参是一样的,属于 值传递 方式
应当注意实参与形参的类型保持一致

3.指向结构体数组的指针

程序已定义了指针 p 为指向 struct student 类型数据的变量
它只能指向一个 struct student 型的数据(p 的值是 stu 数组的一个元素的起始地址)
而不能指向 stu 数组元素中的某一成员,(即 p 的地址不能是成员地址)例如,下面是不对的:p = &stu[1].name此时,在 p 中存放 stu[1] 元素的 name 成员的起始地址p = (struct student *)&stu[1].name;
#include <stdio.h>
#inlcude <stdlib.h>struct student
{int num;char name[20];char sex;int age;
};struct student stu[3] = {{10101, "Li Lin", 'M', 18},{10102, "Zhang Fun", 'M', 19},{10103, "Wang Min", 'F', 20}};int main()
{struct student *p;printf("No.    name        sex        age\n");for(p=stu; p<stu+3;p++)printf("%5d %-20s %2c %4d\n", p->num, p->name, p->sex, p->age);system("pause");
}运行结果如下:
No.    name        sex      age
10101 Li Lin        M       18
10102 Zhang Fun     M       19
10103 Wang Min      F       20

五:用指针处理链表

1.链表概述

struct student
{int num;float score;struct student *next;
};

其中成员 num 和 score 用来存放结点中的有用数据(用户需要用到的数据)

next 是指针类型成员,它指向 struct student 类型数据(这是 next 所在结构体类型)

2.简单链表例子

#include <stdio.h>
#include <stdlib.h>#define NULL 0struct student
{long num;float score;struct student *next;
};void main()
{struct student a, b, c, *head, *p;a.num = 99101; a.score = 89.5;b.num = 99103; b.score = 90;c.num = 99107; c.score = 85;//对结点的 num 和 score 成员赋值head = &a;//将结点 a 的起始地址赋给头指针 heada.next = &b;//将结点 b 的起始地址赋给 a 结点的 next 成员b.next = &c;c.next = NULL;// c 结点的 next 成员不存放其他结点地址p = head;//使 p 指针指向 a 结点do{printf("%ld %5.1f\n", p->num, p->score);// 输出 p 指向的结点的数据p = p->next;//使 p 指向下一结点}while(p != NULL);//输出完 c 结点后 p 的值为 NULLsystem("pause");
}

运行结果:

99101  89.5
99103  90.0
99107  85.0

3.建立动态链表

是指在程序执行过程中从无到有地建立起一个键表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系

#include <stdio.h>
#include <stdlib.h>#define NULL 0
#define LEN sizeof(struct student)struct student
{long num;float score;struct student *next;
};struct student *create()
{struct student *p1, *p2, *head;int num;float score;int n = 0;head = NULL;p1 = p2 = (struct student *)malloc(LEN);printf("please input num and score.\n");scanf("%d,%f", &p1->num, &p1->score);while(p1->num != 0){n ++;if(n == 1)head = p1;elsep2->next = p1;p2 = p1;p1 = (struct student *)malloc(sizeof(struct student));printf("please input num and score.\n");scanf("%d,%f", &p1->num, &p1->score);}p2->next = NULL;return head;
}void printlist(struct student *head)
{struct student *p;p = head;if(head != NULL){do{printf("num=%d score=%f\n", p->num, p->score);p = p->next;}while(p != NULL);}
}void main()
{struct student *head;head = create();printlist(head);system("pause");
}

3.1 打印链表

void printlist(struct student *head)
{struct student *p;p = head;if(head != NULL){do {printf("num=%d score=%5.2f\n", p->num, p->score);p = p->next;} while (p != NULL);}/* while(p -> next != NULL){printf("num=%d score=%f\n", p->num, p->score);p = p->next;}*/
}

3.2 删除节点

struct student *delNode(struct student *head, int num)
{printf("delNode.\n");struct student *p1, *p2;if(head == NULL){printf("The List is NULL.\n");}else{p1 = head;while(p1->next != NULL && p1->num != num){p2 = p1;p1 = p1->next;}if(p1->num == num){if(p1 == head)head = p1->next;elsep2->next = p1->next;}elseprintf("Can not find list num.\n");}return head;
}

3.3 更新节点

struct student *update(struct student *head, int index, int num, float score)
{printf("update.\n");struct student *p;if(head == NULL){printf("The List is NULL.\n");}else{p = head;while(p->next != NULL && p->num != index){p = p->next;}if(p->num == index){p->num = num;p->score = score;}elseprintf("Can not find list index.\n");}return head;
}

3.4 增加节点

struct student *add(struct student *head, int index, int num, float score)
{printf("add.\n");struct student *p1, *p2, *p3;if(head == NULL){printf("The List is NULL.\n");}else{p1 = p2 = head;while(p1->next != NULL && p1->num != index){p1 = p1->next;p2 = p1;}if(p1->num == index){p3 = (struct student *)malloc(LEN);p3->num = num;p3->score = score;if(p2->next == NULL){p2->next = p3;p3->next = NULL;}else{p3->next = p2->next;p2->next = p3;   }}elseprintf("Can not find list index.\n");}return head;
}

五:几个结构体中常用的函数memcpy() memset() bzero()

1.结构体的复制函数memcpy

在C语言中,结构体的成员如果是基本数据类型(int、char、double)可以用=号赋值如果是字符串,字符串不是基本数据类型,可以用strcpy函数赋值如果要把结构体变量的值赋给另一个结构体变量,有两种方法:1)一种是把结构体变量成员的值逐个赋值给另一个结构体变量的成员,这种方法太笨,没人使用;2)另一种方法是内存拷贝,C语言提供了memcpy(memory copy的简写)实现内存拷贝功能。

函数声明:

void *memcpy(void *dest, const void *src, size_t n);memcpy(&girl2,&girl1,sizeof(struct st_girl));参数说明:src 源内存变量的起始地址。dest 目的内存变量的起始地址。n 需要复制内容的字节数。函数返回指向dest的地址,函数的返回值意义不大,程序员一般不关心这个返回值

2.内存空间赋值函数memset

memset 函数是内存空间赋值函数,用来给某一块内存空间进行赋值的包含在<string.h>头文件中

函数的声明如下:

void *memset(void *s, int v, size_t n);s为内存空间的地址,一般是数组名或结构体的地址。v为要填充的值,填0就是初始化。n为要填充的字节数。

3.内存空间清零函数bzero

bzero函数是内存空间清零。包含在<string.h>头文件中。

函数的声明如下:

void bzero(void *s, size_t n);s为内存空间的地址,一般是数组名或结构体的地址。n为要清零的字节数。

如果要对数组或结构体清零,用memset和bzero都可以,没什么差别

C复合结构——结构体struct相关推荐

  1. linux 结构体 struct addrinfo 简介

    目录 定义 相关方法 1. getaddrinfo(const char, const char, const struct addrinfo, struct addrinfo*) 2. freead ...

  2. 结构体struct timeval 和 struct timespec的定义

    结构体struct timeval 和 struct timespec的定义均在头文件<sys/time.h>中,具体定义如下: struct timeval {long tv_sec; ...

  3. Golang结构体struct的使用(结构体嵌套, 匿名结构体等)

    转自: https://studygolang.com/articles/11313 golang中是没有class的,但是有一个结构体struct,有点类似,他没有像java,c++中继承的概念,但 ...

  4. linux sock结构体,struct socket结构体详解

    在内核中为什么要有struct socket结构体呢? struct socket结构体的作用是什么? 下面这个图,我觉得可以回答以上两个问题.  由这个图可知,内核中的进程可以通过使用struct ...

  5. 内核中用于数据接收的结构体struct msghdr

    我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,ping另一台主机172.16.48.1.我们使用系统调用send ...

  6. C/C++结构体struct 与结构体数组和枚举型enum的结合使用

    C/C++结构体struct 与结构体数组和枚举型enum的结合使用 #include "stdafx.h" #include <string> #include &l ...

  7. 内核中用于数据接收的结构体struct msghdr以及iovec介绍

    我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,ping另一台主机172.16.48.1.我们使用系统调用send ...

  8. 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

    http://blog.csdn.net/windeal3203/article/details/39320605 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq ...

  9. C语言 结构体 struct Cat cat1;

    引入 使用传统技术解决 需要定义多个变量或数组 结构体与结构体变量的关系示意图 类似Java类中的对象(结构体)与属性(结构体变量) 一切物体都可以看作对象(结构体) 补充:C语言数据类型 简单使用案 ...

  10. go struct 静态函数_Go语言学习笔记(四)结构体struct 接口Interface 反射reflect...

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struc ...

最新文章

  1. MongoDB 文档的更新操作
  2. UITableView性能优化与卡顿
  3. Bootstrap导航栏
  4. mac下搭建lua环境
  5. 如何在virtualbox中对虚拟机截图
  6. C语言程序设计 文件操作函数
  7. 默认select选中其中一个option的值
  8. 【C语言】指针(野指针)
  9. 十天学会单片机(3)发光管闪烁,蜂鸣器发声
  10. x80hd装linux,平板垃圾佬 篇五:台电也能打十个!x80hd双系统8寸的身体2G+32G的心胸~...
  11. 7、python数据框重复值的查找和删除
  12. 解决高德地图闪屏黑屏
  13. 设计原则 - 单一职责原则
  14. java保留字详解_下列( )不是Java中的保留字?
  15. 机器学习算法常见面试题目总结
  16. 【NI Multisim 14.0原理图设计基础——元器件分类】
  17. Hadoop分布式集群环境准备--无线网下VMware虚拟机设置
  18. svipfuli.php,【www.svipfuli3.com】下载 - 面包树
  19. Android微信动态调试,Android远程调试的探索与实现
  20. 基于java会议管理系统设计(含源文件)

热门文章

  1. mysql 怎么 增加新用户名和密码_在mysql中怎么添加用户名和密码
  2. Vue前端技术知识整理
  3. 2015—2016年QS世界大学排名200强-[转]
  4. 坚守自主创新,璞华HawkEye IETM系统惠及国计民生
  5. 有哪些APP小众却实用,让你相见恨晚
  6. 创建自己的腾讯云存储桶,将图片上传到腾讯云,并实现父子之间的数据双向绑定
  7. 魔王抓住了公主 等笑话
  8. 用魔法打败魔法,传染性疫苗能消灭传染病吗?
  9. MATLAB图像处理
  10. mysql中dint_MySQL基础篇(1)SQL基础