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比特