结构体
多种数据类型变量的自定义集合被称为结构体,结构体同样也是一种数据类型
结构体定义
//定义一个结构体类型
struct 结构体类型名称{
int ; //member1
char ;//member2
float ;//member3
short ;//member4
...
};
//定义一个结构体
struct 结构体类型名称{
int ; //member1
char ;//member2
float ;//member3
short ;//member4
...
} 所定义的结构体名;
//将结构体类型简写
typedef struct 结构体类型名称{
int ; //member1
char ;//member2
float ;//member3
short ;//member4
...
} 结构体类型名简写;
结构体内容访问
结构体内容访问中使用的的格式控制符与是否取地址取决于最终内容的数据类型。
scanf("%d,%s",&结构体名称.内容名称,结构体名称.内容名称);
scanf("%d,%s",结构体名称.内容名称,结构体名称.内容名称);
下为一个结构体数组的访问例子:
#include<stdio.h>
struct s1{
char name[10];
int id;
};
int main(){
int i;
struct s1 user[10];
for(i=0;i<10;i++){
scanf("%s%d",user[i].name,&user[i].id);
}
for(i=0;i<10;i++){
printf("%s,%d\n",user[i].name,user[i].id);
}
return 0;
}
结构体指针
即指向结构体的指针,使用指针访问结构体内容时是否取地址同样取决于内容的数据类型
struct 结构体类型名称 *结构体指针名称=&结构体名称
//结构体需要取地址,虽然结构体名的确是首地址
scanf("%d,%s",&结构体名称->内容名称,结构体名称->内容名称);
scanf("%d,%s",结构体名称->内容名称,结构体名称->内容名称);
//指针访问内容时与结构体访问时不同,使用的是->
下为一个结构体指针的访问例子:
#include<stdio.h>
typedef struct stu{
char name[20];
int age;
} s;
int main(){
s class1;
s *cc=&class1;
scanf("%s%d",cc->name,&cc->age);
printf("%s %d",cc->name,cc->age);
}
结构体嵌套
即在一个结构体的内容里包含另一种类型的结构体或结构体指针。
使用一层指针访问嵌套结构体内容的例子:
#include<stdio.h>
typedef struct stu{
char name[20];
int age;
} s;
typedef struct peo{
int id;
s stus;
} p;
int main(){
p c1;
p *cp=&c1;
scanf("%d%s%d",&cp->id,cp->stus.name,&cp->stus.age);
printf("%d %s %d\n",cp->id,cp->stus.name,cp->stus.age);
}
使用两级指针访问嵌套结构体指针内容的例子:
#include<stdio.h>
typedef struct{
char name[20];
int age;
} s;
typedef struct{
int id;
s *sp;
} p;
int main(){
p pi;
p *pp=π
s si;
pp->sp=&si;
scanf("%d%s%d",&pp->id,pp->sp->name,&pp->sp->age);
printf("%d %s %d\n",pp->id,pp->sp->name,pp->sp->age);
}
共用体
与结构体不同的是,共用体内容成员公用同一片内存空间,内容输入会覆盖掉之前输入的另一成员的内容。所占用的内存空间取决于占用最大内存空间的成员。
//定义一个共用体类型
union 共用体类型名称{
int ; //member1
char ;//member2
float ;//member3
short ;//member4
...
};
//定义一个共用体
union 共用体类型名称{
int ; //member1
char ;//member2
float ;//member3
short ;//member4
...
} 所定义的共用体名;
//将共用体类型简写
typedef union 共用体类型名称{
int ; //member1
char ;//member2
float ;//member3
short ;//member4
...
} 共用体类型名简写;
枚举
枚举就是定义了一串有规律的宏,表达式依次加一。
enum 枚举名{
内容1,
内容2,
...
内容n,
};
//其实同理为
#define 内容1 1
#define 内容2 2
#define 内容n n
第一个枚举从0开始,之后依次加1。
如果中间赋值,则赋值之后的内容是从赋值量开始依次加一。
#include<stdio.h>
enum a{
mon,
tue,
wed,
thu=12,
fri,
sat,
sun,
};
int main(){
printf("%d,",mon);
printf("%d",sun);
}
上例子中输出结果为“0,15”。
字节对齐
实际上结构体各个内容成员并不是紧密存放在内存空间中的。在32bit OS中,是以4Bytes为单位进行分配的,而在64bitOS中是以8Bytes为单位进行分配的。
当内容成员的数据类型所占内存空间超过了上一内容成员剩余的内存空间,就会重新分配内存空间,小于则使用上一成员分配剩余的内存空间。
以32bitOS为例:
struct s1{
char name[20];
int num;
int nnum;
}
struct s2{
char name[20];
double num;
}
虽然两个结构体中的内容成员从数据类型上说,占用空间大小应该是一致的,但是s1占用28字节,s2占用32字节。
下为图解: