C语言结构体

我们的 system 函数,是 C 语言调用其他语言的一个接口,
system(“pause”),是我们通过 C 语言调用执行了 windows 的批处理命令 pause。

如何显示代码行数

首先如何把代码的行号显示出来,如图 1.5-1,选择菜单栏工具中的选项,然后显示如
图 1.5-2 所示,点击文本编辑器,选择 C/C++,然后勾选行号,再点击确定,这时代码里的
行号就显示出来了。

一、结构体定义

    1,三种定义方式

2,解释

一、结构体概述
1 //struct 是结构体关键字 stu是结构体类型名
2 //使用结构体类型 必须是 struct stu3     //num name age 叫做结构体中的成员
4 //定义结构体类型的时候 不要给成员 赋值(重要)
5 //定义结构体类型的时候 并没有分配空间 所以 不能给成员赋值

二、定义一个结构体类型
6 struct stu
{ int num=10;    //4B
9 char name[32];    //32B
10 int age;      //4B
11 };            //一定要记得有;号
12 //结构体中的成员 拥有独立的空间(重要)
13 sizeof(struct stu)= 40

三、用类型定义变量
sruct stu 是类型,用类型去定义变量,stuct stu lucy
但是这样定义的lucy没有赋值,内容不确定

四、给变量中的成员赋值
结构体变量的赋值
lucy.num=100;
注意字符串怎么赋值,用strcpy
strcpy(lucy.name,"奥利给");
lucy.age=18;
pritrf("%d %s %d",xxxxx);

五、结构体变量的初始化
struct stu lucy={100,"德玛西亚",18 };    注意顺序保持一致
那如何清空结构体变量
memset(&lucy,0,sizeof(lucy));

六、结构体变量获取键盘输入
 void test04() 
{ 
struct stu lucy; 
memset(&lucy, 0,sizeof(lucy));
printf("请输入num name age:");
  //&lucy.num 取的是num成员地址 
scanf("%d %s %d",&lucy.num, lucy.name , &lucy.age);
printf("num=%d, name=%s, age=%d\n",lucy.num,lucy.name,lucy.age); }

七,结构体变量之间的赋值
法一,逐个成员赋值
法二,相同类型的结构体变量,可以直接赋值,bob=lucy
法三,底层实现,memcpy(&bob,&lucy,sizeof(stuct stu));

八,结构体数组
1 void test06()
2 {
3  struct stu arr[5]={    //    定义一个数组,用结构体定义一个变量,替换
4  {100,"小法",18},
5  {101,"德玛西亚",19},
6  {102,"盲僧",20},
7  {103,"快乐风男",30},
8  {104,"提莫",8}
9  };
10  int n = sizeof(arr)/sizeof(arr[0]);
11  int i=0;
12
13  for(i=0;i<n;i++)
14  {
15  printf("num=%d, name=%s, age=%d\n",arr[i].num,arr[i].name,arr[i].age);
16  }
17 }

九、冒泡排序
1 #include<stdlib.h>
2 void test08()
3 {
4  int n = 0;
5  int i=0,j=0;
6  int *arr = NULL;
7  printf("请输入数据的个数:");
8  scanf("%d", &n);
9
10  //根据元素的个数申请空间
11  arr = (int *)calloc(n,sizeof(int));
12  if(NULL == arr)
13  {
14  perror("calloc");
15  return;
16  }
17
18  //键盘给动态数组 获取输入
19  printf("请输入%d个int数据\n", n);
20  for(i=0;i<n;i++)
21  {
22  scanf("%d", arr+i);//arr+i 第i个元素的地址
23  }
24
25  //排序
26  for(i=0;i<n‐1;i++)
27  {
28  int flag = 0;
29  for(j=0;j<n‐i‐1;j++)
30  {
31  if(arr[j]>arr[j+1])//从小‐‐‐>大 交换
32  {
33  int tmp = 0;
34  tmp = arr[j];
35  arr[j]=arr[j+1];
36  arr[j+1]=tmp;
37  flag = 1;
38  }
39  }
40
41  if(flag == 0)//数组已经有序
42  break;
43  }
44  printf("i=%d\n",i);
45
46  //数组的遍历
47  for(i=0;i<n;i++)
48  {
49  printf("%d ",arr[i]);
50  }
51  printf("\n");
52
53  //释放空间
54  if(arr != NULL)
55  {
56  free(arr);
57  arr=NULL;
58  }
59 }

十、结构体数组排序
//按学号来排
1 void test09()
2 {
3  struct stu arr[5];
4  int i=0,j=0;
5  int n = sizeof(arr)/sizeof(arr[0]);
6  memset(arr,0,sizeof(arr));//整个数组 清0
7
8  //获取键盘输入
9  printf("请输入%d个学生信息\n",n);
10  for(i=0;i<n;i++)
11  {
12  scanf("%d %s %d",&arr[i].num, arr[i].name, &arr[i].age);
13  }
14
15  //根据学号 排序
16  for(i=0;i<n‐1;i++)
17  {
18  for(j=0;j<n‐i‐1;j++)
19  {
20  if(arr[j].num < arr[j+1].num)//按照num的大小排序
21  {
22  struct stu tmp;
23  tmp = arr[j];
24  arr[j]=arr[j+1];
25  arr[j+1]=tmp;
26  }
27  }
28  }
29
30  //遍历
31  printf("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐\n");
32  for(i=0;i<n;i++)
33  {
34  printf("%d %s %d\n",arr[i].num, arr[i].name,arr[i].age);
35  }
36 }


二、结构体指针

          一、typedef 用法

1 //typedef使用步骤:
2 //1、先用已有的类型 定义一个变量
3 //2、用别名 替换 变量名
4 //3、在整个表达式前 添加typedef
5
6 //注意:不能创造新的类型.

一、给int取个别名INT32

7 typedef int INT32;
8 void test01()
9 {
10  INT32 num = 10;
11  printf("num = %d\n", num);//10
12 }

二、给指针取个别名,P_TYPE

1 typedef int *P_TYPE;
2 void test03()
3 {
4  int num = 10;
5  P_TYPE p = &num;//P_TYPE p == int *p
6  printf("*p = %d\n", *p);//10
7 }

三、给函数指针取个别名

1 int my_add(int x,int y)
2 {
3  return x+y;
4 }
5 //FUN_P 是一个函数指针类型 该函数 必须有两个int形参 以及一个int返回值
6 typedef int (*FUN_P)(int x,int y);
7 void test04()
8 {
9  FUN_P p = my_add;
10
11  printf("%d\n", p(100,200));//300
12 }

四、给结构体取个别名

1 typedef struct stu
2 {
3  int num;
4  char name[32];
5  int age;
6 }STU;//此时的STU不是结构体变量 而是结构体类型
7
8 struct stu2
9 {
10  int num;
11  char name[32];
12  int age;
13 }STU2;//变量名
14
15 void test05()
16 {
17  STU lucy={100,"lucy",18};//struct stu lucy
18
19 }

        二、结构体指针

案例,从堆区给结构体申请一个空间

1 void test02()
2 {
3  STU *p = NULL;
4  //从堆区申请结构体空间
5  p = (STU *)calloc(1,sizeof(STU));
6  if(NULL == p)
7  {
8  perror("calloc");
9  return;
10  }
11
12  //获取键盘输入
13  printf("请输入一个学生的信息num name age\n");
14  scanf("%d %s %d", &p‐>num, p‐>name, &p‐>age);
15
16  //遍历
17  printf("num = %d, name=%s, age=%d\n",p‐>num, p‐>name, p‐>age);
18
19  //释放空间
20  if(p != NULL)
21  {
22  free(p);
23  p=NULL;
24  }
25
26  return;
27 }

案例,从堆区申请一个结构体数组 分函数 实现

//铺垫
typedef sruct stu{
    int num;
    char name[32];
    int age;
}STU;
//根据学生个数申请空间  函数
STU *get_addr(int n){
    return (STU*)calloc(1,sizeof(STU))
}
//获取键盘输入函数___用for循环实现

void my_input(STU*arr,int n){
    int i=0;
    for(i=0;i<n;i++){
    printf("请输入第%d个学生的信息",i+1);    //arr代表空间首元素地质
    scanf("%d %s %d",&arr[i].num,arr[i].name,&arr[i].age);//什么时候&不要忘!!!
    //优化 scanf("%d %s %d", &(arr+i)‐>num , (arr+i)‐>name, &(arr+i)‐>age);
}

}
//遍历函数
    void my_print(const STU*arr,int n){    //const一写,一看就是糕手,*arr值不能被用户修改
    int i=0;
    for(i=0;i<n;i++){
    printf("%d %s %d\n",(arr+i)->num,(arr+i)->name,(arr+i)->age);
}
}




//从这里开始看
void test04()
{
    int n=0;
    STU *arr=NULL;
    printf("请输入学生的个数");
    scanf(%d,&n);
//根据学生的个数从堆区申请空间
    arr = get_addr(n);
    if(arr==NULL){
    perror("get_addr");
    return;
    }
//从键盘给结构体数组arr输入数据
    my_input(arr,n);
//遍历结构体数组
    my_print(arr,n);
//释放空间
    if(arr!=NULL){
    free(arr);
    arr=NULL;
}

}

 小结,1,设计程序时,先想好主函数或者test里面要实现什么功能,比如,根据学生个数从堆区申请空间,把他封装成函数,主函数里 写STU *arr=NULL;        arr = get_array_addr(n);

然后再去定义函数,怎么定义函数,根据上一行,返回值arr是STU*类型,STU * get_array_addr(int n){}里面直接return就行

2,print遍历函数,传参用const修饰

3,scanf( )要地址,%s要注意

三、结构体的内存对齐

sizeof(struct data)结果是8

案例

1 typedef struct
2 {
3  char a;                        a        00
4  short b;                        b        b
5  char c;                        c        00
6  short d;                        d        d
7 }DATA;

结构体嵌套结构体

1 typedef struct
2 {
3  int x;
4  int y;
5 }DATA2;
6
7 typedef struct
8 {
9  int a;
10  int b;
11  DATA2 c;//结构体变量c 作为了DATA3的成员 叫结构体嵌套结构体
12 }DATA3;

访问的时候一定要访问到最低层date.a.b

赋值的时候 DATA3 data={10,20,{30,40}};最好写上大括号

结构体嵌套结构体的内存对齐

四,位段

1 /位段 一般只考虑unsigned int类型 也可以考虑unsigned char
2 typedef struct
3 {
4  unsigned char a:2;//a只占一个字节中的两位二进制位
5  unsigned char b:2;//b只占一个字节中的两位二进制位
6
7  //相邻位域 可以压缩 (压缩的位数 不能超过 成员自身大小)
8  unsigned char c:5;
9
10 }DATA2;
11
12 void test02()
13 {
14  printf("%d\n", sizeof(DATA2));//2
15 }
位段的使用:
1 /位段 一般只考虑unsigned int类型 也可以考虑unsigned char
2 typedef struct
3 {
4  unsigned char a:2;//a只占一个字节中的两位二进制位
5  unsigned char b:2;//b只占一个字节中的两位二进制位
6
7  //相邻位域 可以压缩 (压缩的位数 不能超过 成员自身大小)
8  unsigned char c:5;
9
10 }DATA2;
11
12 void test02()
13 {
14  DATA2 data;
15
16  printf("%d\n", sizeof(DATA2));//2
17
18  //位段 不能取地址
19  //printf("%p\n", &data.a);
20
21  //位段的赋值 不要超过 位段的大小 a:2
22  data.a = 6;//0110
23  printf("%u\n", data.a);//2
24 }
无意义的位段:占位用
1 typedef struct
2 {
3  unsigned char a:2;//00
4  unsigned char :4;//无意义的位段(占有4位)
5  unsigned char b:2;//11
6 }DATA3;
7
8 void test03()
9 {
10  DATA3 data;
11  memset(&data, 0,1);
12
13  data.a = 0;//00
14  data.b = 3;//11
15
16  printf("%d\n",sizeof(DATA3));
17
18  printf("%#x\n", *(unsigned char *)&data);//1100 0000 //0xc0
19 }
说明:a是低位  b是高位    00bb00aa

应用 

五、共用体

所有成员共同一份空间,复制之后小的值被大的值覆盖

1 union data
2 {
3  char a;
4  short b;
5  int c;
6 };
7 void test05()
8 {
9  union data A;
10  printf("%d\n",sizeof(union data));//4
11
12  A.a = 10;
13  A.b = 20;
14  A.c = 30;
15  //共用体是最后一次 赋值有效(不严谨)
16
17  printf("%d\n", A.a+A.b+A.c);    //90
18 }





共用体 虽然 共有同一份空间 但是从空间读取的字节数 是有成员自身类型决定。
1 union data
2 {
3  char a;
4  short b;
5  int c;
6 };
7 void test05()
8 {
9  union data A;
10  printf("%d\n",sizeof(union data));//4
11
12  A.c = 0x01020304;
13  A.b = 0x0102;
14  A.a = 0x01;
15
16  printf("%#x\n", A.a+A.b+A.c);    //0x01020203 三者右对齐相加
17 }

  • 25
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值