结构体
1、概念
自己定义的类型
2、姿势
1、struct{结构成员;结构成员;};
例如:
struct{
int len;
int h;
int w;
};
struct{
int len;
int h;
int w;
} xx;
xx.len = 20;
xx.h = 160;
xx.w = 160;2、truct 结构标记{结构成员;结构成员;};
*结构标记 结构成员 及变量名字可以相同
例如
struct x{int x;}; struct x x; ---> 没有问题
struct x{int x;} xx;
struct x xx; //等同于上面3、定义
1、struct{成员;成员;} x,y,z;
2、struct 结构标记{结构成员;结构成员;}x,y,z;
4、赋值
例如:
struct point{
int x;
int y;
};
struct point sp;
sp.x = 10; //结构体变量,用点(.)去获取成员
sp.y = 20;
struct point *psp = (struct point *)malloc(sizeof(struct point));
psp->x = 10; //结构体指针变量,用->去获取成员
psp->y = 20;看例子
#include <stdio.h>
#include <string.h>
int main(void)
{
struct{
char name[20];
char addr[50];
int h;
int w;
int xw;
int yw;
int tw;
} mm;
strcpy(mm.name,"Ricci");
strcpy(mm.addr,"xxx");
mm.h = 159;
mm.w = 180;
mm.xw = 36;
mm.yw = 60;
mm.tw = 60;
printf("%s\n",mm.name);
return 0;
}
/**
***********
* 运行结果
* Ricci
**********
*/5、初始化
struct{成员;成员;} x = {成员值,成员值};
struct 结构标记 x = {成员值,成员值};
例如:
struct point{int x;int y};
struct point x = {10,20};
看例子
#include <stdio.h>
#include <string.h>
struct mm{
char name[20];
char addr[50];
int h;
int w;
int xw;
int yw;
int tw;
};
int main(void)
{
struct mm sm;
strcpy(sm.name,"Ricci");
strcpy(sm.addr,"xxx");
sm.h = 159;
sm.w = 180;
sm.xw = 36;
sm.yw = 60;
sm.tw = 60;
printf("%s\n",sm.name);
struct mm *psm = &sm;
printf("%s\n",psm->addr);
struct mm smm = {"xx","hqyj",170,150,10,10,10};
printf("%s\n",smm.name);
printf("%s\n",(&smm)->addr);
return 0;
}
/**
***********
* 运行结果
* Ricci
* xxx
* xx
* hqyj
**********
*/6、取别名
typedef struct{成员;成员;} 别名;
typedef struct 结构标记{结构成员;结构成员;} 别名;
例如:
typedef struct point sp_t;
sp_t xx = {10,20};7、使用
struct point{int x;int y};
main{
struct point sp; // int a;
sp.x = 10; //结构体变量,用点(.)去获取成员
sp.y = 20
struct point *psp = (struct point *)malloc(sizeof(struct point));
psp->x = 10; //结构体指针变量,用->去获取成员
psp->y = 20;
}8、结构体算字节数
1、32位操作系统最大按照4字节对其
2、64位操作系统最大按照8字节对其
3、每个数据成员存储的起始位置是自身大小的整数倍
4、结构体总大小(也就是sizeof的结果),必须是该结构体成员中最大的对齐模数的整数倍
例子:在32操作系统中
struct xx{
char sx[23];
int sex; //0 1
double d;
short b;
char xs[21];
int *p;
char c;
short s;
int xx;
}; ---> 729、手动修改结构体的对其方式
#pragma pack(n) n为 2的次方数 1 2 4 8 16 32
#include <stdio.h>
#pragma pack(4)
struct person{
char name[18];
int sex;
int age;
char wh[20];
char *hobby[20];
float sc;
};
int main(void)
{
printf("%lu\n",sizeof(struct person));
struct person sp;
printf("%d\n",(int)((char *)&sp.sex-(char *)&sp));
return 0;
}
/**
***********
* 运行结果
* 212
* 20
**********
*/位域
1、概念
带有预定宽度的变量称为位域
2、姿势
struct 标签{
位域类型 位域变量名:位域宽度;
位域类型 位域变量名:位域宽度;
};
例子:
struct xx{
int a:2; //占2位 00 01 10 11
unsigned b:4; //占4个位
};3、位域类型
位域类型为整型,例:char、short、int 、unsigned int(简写为unsigned)
4、位域宽度
1、不能超过该类型的的大小
例子:int a:33 //错误
2、赋值时不能超过该类型的承受范围
例子:
unsigned char a:2 // 00 01 10 11那么a只能存 0 1 2 3这几个数字
a = 5; //错误
5、位域对齐
位域类似结构体,按照最大类型对齐,但是Linux中类型与类型之间挨着
6、空域
位域宽度为0的位域称为空域,其作用是:该次对齐空间剩余部分全部补0
例子:
struct xx{
int b:1 ;
int :0 ; // 32位对齐,所以该处共有31个0
int c:3 ; // 新的对齐行
}7、无名位域
位域没有名字,仅仅占用空间,无名位域不能调用,其作用是隔开两个位域
例子:
struct xx{
unsigned a:2
unsigned: 3 //无名位域,将a和c隔开3个位,该3个位不能使用
unsigned c:2
}8、位域大小计算(存储规则)
1、如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止
2、如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍
3、如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++,GCC采取压缩方式
4、如果位域字段之间穿插着非位域字段,则不进行压缩
9、使用的测试
#include <stdio.h>
#include <string.h>
//无名位域
struct xx{
int a:5;
int :3;
int c:4;
};
int main(void)
{
printf("%lu\n",sizeof(struct xx));
struct xx sx;
bzero(&sx,4);
sx.a = 0x1a;
//sx.b = 0xa;
sx.c = 0xb;
printf("%#hhx\n",*((unsigned char *)&sx+0)); //
printf("%#hhx\n",*((unsigned char *)&sx+1)); //
printf("%#hhx\n",*((unsigned char *)&sx+2)); //
printf("%#hhx\n",*((unsigned char *)&sx+3)); //
// printf("%#hhx\n",*((unsigned char *)&sx+4)); //
return 0;
}
/**
***********
* 运行结果
* 4
* 1x1a
* 0xb
* 0
* 0
**********
*/