1 产生及意义
2 类型描述
struct 结构体名
{
数据类型 成员1;
数据类型 成员2;
数据类型 成员3;
...............
};
3 嵌套定义
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 32
struct simple_st
{
int i,j;
float f;
char ch;
};
struct birthday_st
{
int year;
int month;
int day;
};//定义
struct student_st
{
int id;
char name[NAMESIZE];
struct birthday_st birth;//嵌套方式一
struct math
{
char name[];
int before score;
int average;
}math_inf;//嵌套方式二
int chinese;
};
int main()
{
}
4 定义变量(变量、数组、指针),初始化及成员引用
成员引用:变量名 .成员名
指针名 ->成员名
(*指针) .成员名
注意:只能在初始化时全部赋值,其他情况下需要单个引用的方式赋值
初始化及成员引用方法一:
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 32
struct simple_st
{
int i;
float f;
char ch;
};
int main()
{
//TYPE NAME = VALUE;
struct simple_st a = {123,456.789,'a'};//赋值
a.i = 112233;//修改值
printf("%d\t%f\t%c\n",a.i,a.f,a.ch);//打印
}
初始化及成员引用方法二:
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 32
struct birthday_st
{
int year;
int month;
int day;
};
struct student_st
{
int id;
char name[NAMESIZE];
struct birthday_st birth;
int math;
int chinese;
};
int main()
{
//TYPE NAME = VALUE;
struct student_st stu = {10011,"Alan",{2011,11,11},98,97};//全部赋值
printf("%d %s %d-%d-%d %d %d\n",stu.id,stu.name,stu.birth.year,stu.birth.month,stu.birth.day,stu.math,stu.chinese);//变量名.成员名方式打印
}
初始化及成员引用方法三:
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 32
struct birthday_st
{
int year;
int month;
int day;
};
struct student_st
{
int id;
char name[NAMESIZE];
struct birthday_st birth;
int math;
int chinese;
};
int main()
{
//TYPE NAME = VALUE;
struct student_st stu = {.math = 98,.chinese = 97};// .成员名 (部分赋值)
printf("%d %d",stu.math,stu.chinese);//打印
}
初始化及成员引用方法四:
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 32
struct birthday_st
{
int year;
int month;
int day;
};
struct student_st
{
int id;
char name[NAMESIZE];
struct birthday_st birth;
int math;
int chinese;
};
int main()
{
//TYPE NAME = VALUE;
struct student_st stu = {10011,"Alan",{2011,11,11},98,97};//赋值
struct student_st *p = &stu;//定义一个指向stu的结构体类型的指针
printf("%d %s %d-%d-%d %d %d\n",p->id,p->name,p->birth.year,p->birth.month,p->birth.day,p->math,p->chinese);// 指针名 ->成员名 打印
printf("%d %s %d-%d-%d %d %d\n",(*p).id,(*p).name,(*p).birth.year,(*p).birth.month,(*p).birth.day,(*p).math,(*p).chinese);// (*指针名).成员名 打印
}
结构体数组:
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 32
struct birthday_st
{
int year;
int month;
int day;
};
struct student_st
{
int id;
char name[NAMESIZE];
struct birthday_st birth;
int math;
int chinese;
};
int main()
{
//TYPE NAME = VALUE;
int i;
struct student_st *p;//定义一个指向结构体的指针
struct student_st arr[2] = {{10011,"Alan",{2011,11,11},98,97},{10012,"Dasiy",{2012,11,11},90,99}};//赋值
p = &arr[0]; //p = arr;指针指向数组的起始地址
for(i = 0 ; i < 2 ; i++,p++)//循环打印,p++ ->p = p+1
{
printf("%d %s %d-%d-%d %d %d\n",p->id,p->name,p->birth.year,p->birth.month,p->birth.day,p->math,p->chinese);//打印
}
}
5 占用内存空间大小
根据成员位置分配线性存储内存
结构体地址对齐:
add % sizeof(数据类型) linux默认4字节对齐(结构体整体对齐)
例如,结构体中第一个成员为int 型,占用四个字节,即地址的0,1,2,3
结构体的第二个成员为char型,从第四个地址开始,即arr = 4, arr % sizeof(char) = 0 ,地址对齐可以存放,该数据就存放在4
结构体的三个成员为float型 ,从第五个地址开始,即arr = 5,arr % sizeof(float) ,即5 % 4 = 1(不满足),地址加一,
6 % 4 = 2(不满足),7 % 4 = 3(不满足),地址加一,8 % 4 = 0(满足要求),所以该float型的值从地址8开始,即地址5,6,7没有内容
#include <stdio.h>
#include <stdlib.h>
struct simpl_st
{
int i;
float f;
char ch;
};//定义结构体
int main()
{
struct simpl_st st;//初始化
struct simpl_st *p = &st;//定义一个结构体指针指向结构体
printf("sizeof(st) = %d\n",sizeof(st));//打印结构体占用的字节数
printf("sizeof(p) = %d\n",sizeof(p));//打印指针占用的字节数
exit(0);
}
在跨网络传输时,不能使用地址对齐
因为传输端与接收端的地址对齐规则可能不一样
解决办法:使用宏 __ attribute__((packed))
#include <stdio.h>
#include <stdlib.h>
struct simpl_st
{
int i; //4
float f;//4
char ch;//1
}__attribute((packed));//地址不对齐,4+4+1 = 9
int main()
{
struct simpl_st st;
struct simpl_st *p = &st;
printf("sizeof(st) = %d\n",sizeof(st));打印结构体占用的字节数
printf("sizeof(p) = %d\n",sizeof(p));//打印
exit(0);
}
6 函数传参(值 ,地址)
值传参(结构体):
#include <stdio.h>
#include <stdlib.h>
struct simpl_st
{
int i;
float f;
char ch;
};
void func(struct simpl_st b)//值接受,重新定义一片空间来接受与结构体一样大小的内容,比较浪费内容
{
printf("sizeof(b) = %d\n",sizeof(b));//形参的大小为12,与结构体一样
}
int main()
{
struct simpl_st st;
struct simpl_st *p = &st;
printf("sizeof(st) = %d\n",sizeof(st));
printf("sizeof(p) = %d\n",sizeof(p));
func(st);//传入结构体名
exit(0);
}
用指针传参(结构体)(节省内存)
#include <stdio.h>
#include <stdlib.h>
struct simpl_st//定义结构体
{
int i;
float f;
char ch;
};
void func(struct simpl_st *b)//指针形参
{
printf("sizeof(b) = %d\n",sizeof(b));//打印形参大小,为8,当传入的结构体比较大时,指针传参比值传参更省内存
}
int main()
{
struct simpl_st st;
struct simpl_st *p = &st;
printf("sizeof(st) = %d\n",sizeof(st));
printf("sizeof(p) = %d\n",sizeof(p));//sizeof(&st)
func(p);//指针传参
exit(0);
}
微型学生管理系统
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 32
struct student_st
{
int id;
char name[NAMESIZE];
int math;
int chinese;
};//建立学生信息结构体
void mune(void)
{
printf("\n1 set\t2 changname\t3 show\n\n");
printf("Please enter the num you want to choice(enter q for quit):\n\n");
}//模式选择菜单
void stu_set(struct student_st *p,struct student_st *q)
{
*p = *q;
}//结构体赋值
void stu_changename(struct student_st *p,const char *newname)
{
strcpy(p->name,newname);
}//修改名字
void stu_show(struct student_st *p)
{
printf("%d %s %d %d\n\n",p->id,p->name,p->math,p->chinese);
}//打印信息
int main()
{
int ret,choice,i;
char newname[NAMESIZE];
struct student_st stu,tmp;
do
{
mune();
ret = scanf("%d",&choice);
if(ret != 1)
break;
switch(choice)
{
case 1:
printf("\nPlease enter the student's information :[id][name][math][chinese]:\n");
scanf("%d%s%d%d",&tmp.id,&tmp.name,&tmp.math,&tmp.chinese);
stu_set(&stu,&tmp);
break;
case 2:
printf("\nPlease enter the name you want to change:[name]:\n");
scanf("%s",newname);
stu_changename(&stu,newname);
break;
case 3:
printf("\n");
stu_show(&stu);
break;
default:
printf("Please enter the right number(as 1,2,3)!\n");
exit(-1);
}
sleep(1);
}while(1);
}