一、结构体简介
结构体是一个构造类型,结构体中可以是不同类型成员的集合。也可以是相同类型成员的集合。一般情况下,我们使用结构体都是为了处理不同类型的数据。
1.定义结构体类型的格式
struct 结构体类型名{
数据类型1 成员1;
数据类型2 成员2;
...
数据类型n 成员n;
};
struct Test{
char a;
int b;
}
//变量版
//结构体变量名.成员名
struct Test t1;
t1.a='M';
t1.b=10;
//指针版
//结构体指针名->成员名
struct Test *p1=&t1;
p1->a='H';
p2->a=20;
//也可以用malloc函数自己定义地址空间
struct Test *p2=(struct Test *)malloc(sizeof(struct Test));
p2->a='Q';
p2->b=30;
例子:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct _STUDENT{
int id;
char name[32];
}stu_t;
int main(int argc, const char *argv[]){
//变量版
struct _STUDENT s1;
s1.id=1001;
printf("s1.id=%d\n",s1.id);//1001
stu_t s2;
printf("s2.id=%d\n",s2.id);//随机值
//结构体中有数组成员时,数组成员定义好了也不能直接赋值
//s1.name="zhangsan";//错误的
strcpy(s1.name,"zhangsan");
strcpy(s2.name,"lisi");
printf("s1.name=[%s]\n",s1.name);//zhangsan
printf("s2.name=[%s]\n",s2.name);//lisi
//指针版
struct _STUDENT *p1=&s1;
printf("p1->id=%d\n",p1->id);
printf("p1->name=%s\n",p1->name);
stu_t *p2=(stu_t *)malloc(sizeof(stu_t));
p2->id=1234;
strcpy(p2->name,"wangwu");
printf("p2->id=%d\n",p2->id);
printf("p2->name=%s\n",p2->name);
free(p2);
p2=NULL;
return 0;
}
结构体也可以定义数组:
struct 结构体类型名 数组名[下标];
操作结构体数组中的元素时 和 操作单个的结构体变量是一模一样的。
2.结构体数组的初始化和赋值
方式1:
struct Test{
int a;
char b[32];
char c;
};
struct Test s[2];
s[0].a=10;
strcpy(s[0].b,"hello");
s[0].c=20;
s[1].a=30;
strcpy(s[1].b,"beijing");
s[1].c=40;
方式2:
struct Test{
int a;
char b[32];
char c;
};
struct Test s[2] ={
{10,"zhangsan",20},
{30,"lisi",40}
};
方式3:
struct Test{
int a;
char b[32];
char c;
};
struct Test s[3]={
[0]={10,"zhangsan",20},
[2]={30,"lsii",40},
};
方式4;
struct Test{
int a;
char b[32];
char c;
};
struct Test s[3]={
[0]={.a=10,.b="zhangsan"},
[1]={.a=30,.c=40}
};
3.结构体清零
这里需要memset函数清0。
void *memset(void *s, int c, size_t n);
typedef struct _STUDENT{
int id;
int b;
}stu_t;
int main(int argc, const char *argv[]){
//栈区
stu_t t1;
memset(&t1,0,sizeof(t1));
//堆区
stu_t *p1=(stu_t *)malloc(sizeof(stu_t));
memset(p1,0,sizeof(stu_t));
return 0;
}
4.C语言中结构体不能定义函数,但是可以定义函数指针
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void printf_hello(){
printf("hello\n");
}
void printf_beijing(){
printf("beijing\n");
}
typedef struct Test{
int a;
char b;
void (*p)();
}stu_t;
int main(int argc, const char *argv[]){
stu_t t1;
t1.p=printf_hello;
t1.p();
stu_t t2;
t2.p=printf_beijing;
t2.p();
return 0;
}
5.结构体对齐问题
5.1在64位系统中
按结构体中最大的成员对齐。
struct Test{
long double a;
char b;
};//32
5.2在32位系统中
1.如果成员都不超过4字节,按照最大的成员对齐。
2.如果成员大于等于4字节,则都按4字节对齐。
3.要特别注意char和short连续存储的问题。
//验证第一条
struct Test{
char a;
char b;
};//2
//验证第二条
struct Test{
char a;
short b;
};//4
//验证第三条
struct Test[
int a;
char b;
short d;
char c;
};//12
//验证第四条
struct Test{
int a;
short d;
char b;
char c;
};//8
6.使用结构体位域来压缩结构体
#include <stdio.h>
//使用结构体位域可以将一个字节拆成多份儿使用
struct LED{
unsigned char led0:1;//使用 冒号 指定成员只占用几个bit位
unsigned char led1:1;
unsigned char led2:1;
unsigned char led3:1;
unsigned char led4:1;
unsigned char led5:1;
unsigned char led6:1;
unsigned char led7:1;
};
int main(int argc, const char *argv[]){
printf("%ld\n", sizeof(struct LED));//1
struct LED my_led;
my_led.led0 = 1;
printf("%d\n", my_led.led0);//1
my_led.led1 = 0;
printf("%d\n", my_led.led1);//0
//...
//注意:压缩之后能存储的数据范围也随之变小了
//使用时不要超过范围
//my_led.led6 = 2;
//printf("%d\n", my_led.led2);//0
return 0;
}