struct关键字及内存对齐详解

struct关键字

空结构体有多大?

struct student
{
}stu;
cout<<sizeof(stu)<<endl;//在vc6.0下是1
因为为需要一个字节来标记这里有个结构体,否则如果是0的话,定义下一个结构体的时候,会和空结构体公用一个地址,无法分别。
结构体不能递归自包含定义,如下:
struct A
{
    int i;
    B b;
}
struct B
{
    char ch;
    A a;
}

假设A定义在B的前面,于是计算A的大小就需要知道B的大小,而计算B的大小有需要直到A的大小,于是。。。。 
虽然对象不能自包含但是,对象可以自引用(holds a)(链表的实现原理),如下 

这个时候 A和B的大小都可以确定; 
类似的还有拷贝构造函数,拷贝构造要传引用,因为传对象的值的话,会无限制的递归下去。

柔性数组

#include<iostream>
using namespace std;
typedef struct st_type
{
    int i;
    int a[0];
}type_a;
int main()
{

    cout << sizeof(type_a) << endl;
    system("pause");
}

这样我们就可以定义一个可变长的结构体,用sizeof(type_a)得到的只有4,就是sizeof(i)=sizeof(int)。那个0个元素的数组没有占用空间,而后我们可以进行变长操作了。通过如下表达式给结构体分配内存:

        type_a*p=(type_a*)malloc(sizeof(type_a)+100*sizeof(int));

这样我们为结构体指针p分配了一块内存。用p->item[n]就能简单地访问可变长元素。但是这时候我们再用sizeof(*p)测试结构体的大小,发现仍然为4。是不是很诡异?我们不是给这个数组分配了空间么? 
别急,先回忆一下我们前面讲过的“模子”。在定义这个结构体的时候,模子的大小就已经确定不包含柔性数组的内存大小。柔性数组只是编外人员,不占结构体的编制。只是说在使用柔性数组时需要把它当作结构体的一个成员,仅此而已。再说白点,柔性数组其实与结构体没什么关系,只是“挂羊头卖狗肉”而已,算不得结构体的正式成员。 
需要说明的是:C89不支持这种东西,C99把它作为一种特例加入了标准。但是,C99所支持的是incompletetype,而不是zeroarray,形同intitem[0];这种形式是非法的,C99支持的形式是形同intitem[];只不过有些编译器把intitem[0];作为非标准扩展来支持,而且在C99发布之前已经有了这种非标准扩展了,C99发布之后,有些编译器把两者合而为一了。 
当然,上面既然用malloc函数分配了内存,肯定就需要用free函数来释放内存:free(p);经过上面的讲解,相信你已经掌握了这个看起来似乎很神秘的东西。不过实在要是没掌握也无所谓,这个东西实在很少用。

顶顶顶

下列代码是对是错?

#include <stdio.h>
struct
{
	int a;
	int b;
}a;
struct
{
	int a;
	int b;
}*b;
int main()
{
	b = &a;
	return 0;
}

上面的b = &a;这样的赋值是非法的。因为编译器将a和b解析成了两种完全不同的类型。

在结构体类型申明的时候,也频繁的时候typedef来对结构体类型做一个重命名。
例如:

typedef struct Stu
{
	int age;
	char name[20];
}STU;
这里的STU就是结构体类型了,我们可以使用STU来创建结构体对象。
STU student1, student2;
这里不再需要struct关键字,因为这里STU已经是一个完整的类型。

结构体内存对其规则:
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
//对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的值为8
linux中的默认值为4
3.结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的
整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对
齐数)的整数倍

#include<iostream>
using namespace std;
int main()
{
	struct Type
	{
		char a;
		char e;
		int b;
		double c;
	};
	cout << sizeof(Type) << endl;//16
	struct Type1
	{
		double c;
		char a;
		int b;
		char e;
	};
	cout << sizeof(Type1) << endl;//24
	struct Type2
	{
		Type1 a;
		char a1;
		int b1;
	};
	cout << sizeof(Type2) << endl;//32
	struct Type3
	{
		char b;
		int a[3];
		short c;
	};
	cout << sizeof(Type3) << endl;//20
	system("pause");
}


位域:

#include<iostream>
using namespace std;
int main()
{
	struct DateTime
	{
		unsigned int year;
		unsigned int month : 4;
		unsigned int day : 5;
		unsigned int hour : 5;
		unsigned int minute : 6;
		unsigned int second : 6;
		//unsigned int ll : 7;
	};
	//int 是4个字节,4比特+5+5+6+6=26<32;所以一共占8个字节,如果再加7就变成了12
	cout << sizeof(DateTime) << endl;//8
	system("pause");
}


#include <stdio.h>
enum escapes
{
	BELL = '\a',
	BACKSPACE = '\b',
	HTAB = '\t',
	RETURN = '\r',
	NEWLINE = '\n',
	VTAB = '\v',
	SPACE = ' '
}es;
struct A
{
	int a;
	enum escapes B;
}A;
enum BOOLEAN { FALSE = 0, TRUE } match_flag;
void main()
{
	printf("%d bytes \n", sizeof(A));//8bytes
	printf("%d bytes \n", sizeof(enum escapes)); //4 bytes
	printf("%d bytes \n", sizeof(enum escapes)); //4 bytes
	printf("%d bytes \n", sizeof(enum BOOLEAN)); //4 bytes
	printf("%d bytes \n", sizeof(enum BOOLEAN)); //4 bytes
	printf("%d bytes \n", sizeof(match_flag)); //4 bytes
	printf("%d bytes \n", sizeof(SPACE)); //4 bytes
	printf("%d bytes \n", sizeof(NEWLINE)); //4 bytes
	printf("%d bytes \n", sizeof(FALSE)); //4 bytes
	printf("%d bytes \n", sizeof(0)); //4 bytes
	system("pause");
}
//所有枚举常量都占4比特


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值