struct、union、enum and sizeof
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("little\n");
printf("%d\n", *p);
}
else
{
printf("large\n");
} 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的更多相关文章
- SQL的inner join、left join、right join、full outer join、union、union all
主题: SQL的inner join.left join.right join.full outer join.union.union all的学习. Table A和Table B表如下所示: 表A ...
- namespace、struct、enum、union、string(day01)
一 C++概述 C++历史背景 )C++的江湖地位 jave C C++ C# python )C++之父:Bjarne Stroustrup(--) ,Cpre,为C语言增加类的机制 ,Bjarne ...
- oracle之集合操作函数---minus、union、intersect
集合操作符专门用于合并多条select语句的结果,包括:UNION,UNION ALL,INTERSECT,MINUS.当使用集合操作函数时,需保证数据集的字段数据类型和数目一致. 使用集合操作符需要 ...
- LINQ标准查询操作符(三)——Aggregate、Average、Distinct、Except、Intersect、Union、Empty、DefaultIfEmpty、Range、Repeat
七.聚合操作符 聚合函数将在序列上执行特定的计算,并返回单个值,如计算给定序列平均值.最大值等.共有7种LINQ聚合查询操作符:Aggregate.Average.Count.LongCount.Ma ...
- Spark RDD/Core 编程 API入门系列之map、filter、textFile、cache、对Job输出结果进行升和降序、union、groupByKey、join、reduce、lookup(一)
1.以本地模式实战map和filter 2.以集群模式实战textFile和cache 3.对Job输出结果进行升和降序 4.union 5.groupByKey 6.join 7.reduce 8. ...
- Linq to SQL -- Union All、Union、Intersect和Top、Bottom和Paging和SqlMethods
Union All/Union/Intersect操作 适用场景:对两个集合的处理,例如追加.合并.取相同项.相交项等等. Concat(连接) 说明:连接不同的集合,不会自动过滤相同项:延迟. 1. ...
- from、where、group、with、having、order、union、limit 的使用
顺序很重要 每次看数据库的一些语法时,都很自然的略过那一大堆的规则,比如说线下面这段select的语法: select [field1,field2...] func_namefrom table1, ...
- Swift中关于集合计算的几种函数记录(intersect、symmetricDifference、union、subtract)
很久之前用过一次,后来就忘了...扎心,现在记录一下 PS:这几种函数其实不限于swift内的,在JavaScript.python.DB等其他语言,应该也有类似用法,这里我只简单讲了在swift内的 ...
- 009-Hadoop Hive sql语法详解4-DQL 操作:数据查询SQL-select、join、union、udtf
一.基本的Select 操作 语法SELECT [ALL | DISTINCT] select_expr, select_expr, ...FROM table_reference[WHERE whe ...
随机推荐
- Azure ServiceBus的消息中带有@strin3http//schemas.microsoft.com/2003/10/Serialization/�
今天碰到一个很讨厌的问题,使用nodejs 接收Azure service bus队列消息的时候,出现了:@strin3http//schemas.microsoft.com/2003/10/Seri ...
- SQL SERVER中获取表间主外键关系
sql server 2008中的主外键关系获取方式: 转自:http://www.cnblogs.com/ke10/archive/2012/06/11/2544655.html SELECT OB ...
- Splay-Tree理解
简介 splay tree其实就是不停的旋转,没进行一个操作都要进行旋转:例如,当访问某一个结点的时候,会通过旋转其结点使得该结点变为树根,这样保证其的平均复杂度为O(nlogn); 其的操作包括: ...
- 读书笔记_Effective_C++_条款三十一:将文件间的编译依存关系降至最低(第三部分)
下面来谈谈书中的第二部分,用Interface Classes来降低编译的依赖.从上面也可以看出,避免重编的诀窍就是保持头文件(接口)不变化,而保持接口不变化的诀窍就是不在里面声明编译器需要知道大小的 ...
- react父子组件数据传递
子传父 1.首先父组件设定一个自定义函数 getChildDatas = (values) => { //...业务代码 } 2.将该函数暴露在子组件的引用上 <Child getChil ...
- 自动化运维工具 ~puppet~
一.模板的应用 到目前为止,资源申报.定义类.声明类等所有功能都只能一个manifest文件中实现,但这却非有效的基于puppet管理IT资源架构的方式.实践 中,一般需要把manifest文件分解成 ...
- sql 递归查询所有的下级
--> 生成测试数据表: [tb] IF OBJECT_ID('[Users]') IS NOT NULL DROP TABLE [Users] GO CREATE TABLE [Use ...
- oracle 锁系列
http://www.cnblogs.com/lhrbest/p/6091277.html
- C#使用反射加载多个程序集
当开发插件的时候需要用到反射,在客户端动态加载遍历程序集,并调用每个程序集的方法. 创建一个控制台应用程序,首先设计一个接口: public interface ISay { void SaySth( ...
- JSON.parse()和jQuery.parseJSON()的区别
jQuery.parseJSON(jsonString) : 将格式完好的JSON字符串转为与之对应的JavaScript对象 (jquery 方法) 1 2 3 var str = '[{&qu ...