struct
1、结构体和数组的区别:可以再结构体里声明数组;结构体变量可以相互赋值,而数组不行。
2、struct与class的区别:class的成员访问权限默认是private,而struct成员的是public。
3、结构体的定义:
(1)可递归。结构体内部可以使用指针指向自己。例如,链表。
(2)可嵌套。结构体内部可以包含其他的结构体。
4、结构体中的位域。
在存储信息时,不需要占用一个完整的字节,而只需要占几个或一个二进制位。
位域定义与结构定义相仿,其形式为:
struct 位域结构名
{
类型说明符 位域名:位域长度
};
例如:
struct bs { int a:8; int b:2; int c:6; }data;
分析:data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。
对于位域的定义尚有以下几点说明:
1. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。
2. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。
例如:
struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*从下一单元开始存放*/
unsigned c:4
}
在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。
union
结构体和共用体都是由多个不同类型的数据类型成员组成,但是在任一时刻,共用体中只存放了一个被选中的成员。而结构体
中所有成员都纯在。对于共用体的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了。
(1)结构体占用内存,可能超过各个成员内存量的和,而共用体占用的内存为各个成员中占用最大者内存。
(2)union和struct在内存中的存放顺序是从地地址开始存放的。
大端存储:数据的高字节存放在低地址中。小端存储:数据的低字节存放在低地址中。
enum
(1)定义
enum 枚举类型名
{
枚举表
}
例如:
enum ColorEnum1
{
红色, //注意,系统会默认给它赋值为0
蓝色, //系统赋值为1
黑色, //系统赋值为2
粉红色 //系统赋值为3
}
enum ColorEnum2
{
红色=1, //用户自己赋值 所以枚举是一组 符号名称/值 配对
蓝色, // 系统赋值为2
黑色=1, //用户自己赋值1
粉红色 //系统赋值为2
}
所以可以看出,系统会自己给没有赋值的常量赋值,但赋值的方式是按照上一个的值+1来进行操作的
sizeof(struct/union/enum)
一般32位机子上各个数据类型所占的存储空间如下:
char:8位
short:16位
int:32位
long:32位
float:32位
double:64位
一、struct,结构体。
请牢记以下3条原则:(在没有#pragma pack宏的情况下)
1、数据成员对齐规则:结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,之后的每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机子上为4字节,所以要从4的整数倍地址开始存储)。
2、结构体作为成员:如果一个结构体里同时包含结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储
(如struct a里有struct b,b里有char,int ,double等元素,那么b应该从8(即double类型的大小)的整数倍开始存储)。
3、结构体的总大小:即sizeof的结果。在按对齐原则计算出来的大小的基础上,必须还得是其内部最大成员的整数倍.
不足的要补齐(如struct里最大为double,现在计算得到的已经是11,则总大小为16)。
例子:
typedef struct bb
{
int id;
//[0]....[3]
表示4字节
double weight;
//[8].....[15] 原则1
float height;
//[16]..[19],总长要为8的整数倍,仅对齐之后总长为[0]~[19]为20,补齐[20]...[23] 原则3
}BB;
typedef struct aa
{
int
id;
//[0]...[3] 原则1
double score;
//[8]....[15]
short grade;
//[16],[17]
BB b;
//[24]......[47] 原则2(因为BB内部最大成员为double,即8的整数倍开始存储)
char name[2]; //[48][49]
}AA;
int main()
{
cout<<sizeof(AA)<<" "<<sizeof(BB)<<endl;
return 0;
}
输出结果为56 24
编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式。//n为1、2、4、8、16...
1、n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默 认的对齐方式,即该变量所占用字节数的整数倍;第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。
2、结构体的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。
所以在上面的代码前加一句#pragma pack(1),则代码输出为
bb:(0~3)+(4~11)+(12~15)=16;
aa:(0~1)+(2~5)+(6~13)+(14~15)+(16~31)=32,也就是说,#pragma pack(1)就是没有对齐规则。
再考虑#pragma pack(4),
bb:(0~3)+(4~11)+(12~15)=16;
aa:(0~1)+(4~7)+(8~15)+(16~17)+(20~35)=36
二、union共用体(联合)
在union中,所有的共用体成员共用一个空间,并且同一时间只能储存其中一个成员变量的值。其长度为联合体中元类型最大的变量长度的整数倍。并且要考虑其他成员变量的对齐。
union foo
{
char s[10];
int i;
}
sizeof(foo) 的内存空间的长度为12,而并不是数组的长度10。考虑对齐,必须要是4(int的大小)的整数倍。
若把int改为double,则foo的内存空间为16,是double型的两倍。
union
mm{
char
a;//元长度1
1
int
b[5];//元长度4
20
double
c;//元长度8
8
int
d[3];
12
};
考虑到8和12的对齐, 所以sizeof(mm)=24。
三、enum
enum只是定义了一个常量集合,里面没有元素,把它当做int型存储,所以sizeof的大小为4 byte。
【大小端】
判断大小端的方法:1、利用指针,2、利用union。
#include <stdlib.h>
#include <stdio.h>
int main()
{
int x = 0x10000001;
char *p = (char *)&x;
if (*p)
{
printf("littlen");
printf("%dn", *p);
}
else
{
printf("largen");
}
system("pause");
return 0;
}
#include "stdio.h"
#include<stdlib.h>
int main()
{
union w
{
int a;
//4 bytes
char b; //1 byte
} c;
c.a = 1;
if (c.b == 1)
printf("It is Little_endian!n");
else
printf("It is Big_endian!n");
system("pause");
return 1;
}
下面这段代码输出也耐人寻味。
#include<stdio.h>
#include<stdlib.h>
union {
char i[4];
short x;
}s;
int main()
{
s.x = 0;
s.i[0] = 256;
s.i[1] = 255;
s.i[2] = 254;
s.i[3] = 253;
printf("s.x is %d n", s.x);
printf("s.i[0] is %d n", s.i[0]);
printf("s.i[1] is %d n", s.i[1]);
printf("s.i[2] is %d n", s.i[2]);
printf("s.i[3] is %d n", s.i[3]);
system("pause");
}
最后
以上就是谦让太阳最近收集整理的关于struct、union、enum and sizeof的全部内容,更多相关struct、union、enum内容请搜索靠谱客的其他文章。
发表评论 取消回复