结构体柔性数组_位域
1. struct中函数
结构体中函数占用字节数:32位主机占用4个字节,64位主机占用8个字节。
结构体中函数本质是指针,占用字节数与指针相同。
#include <stdio.h>
struct student_st {
char name[20];
int no;
void (*show)(struct student_st);
void (*show1)(struct student_st);
};
struct func_st{
void (*print)();
};
void show(struct student_st st)
{
printf("name: %s, no: %d\n", st.name, st.no);
}
int main(int argc, char *argv[])
{
printf("student struct size = %d\n", sizeof(struct student_st));
printf("func struct size = %d\n", sizeof(struct func_st));
struct student_st st = {"wang", 1, show};
st.show(st);
return 0;
}
2. 柔性数组
C99中,柔性数组成员允许结构中包含一个大小可变的数组,但结构中的柔性数组成员前面必须至少一个其他成员。Sizeof返回的这种结构大小不包含柔性数组的内存。
包含柔性数组的结构可用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
注:柔性数组不能直接定义,然后仅malloc柔性数成员,应整体mallo分配空间。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#pragma pack(2) //设置2字节对齐
struct student
{
unsigned char anticollision_front:1;
unsigned char anticollision_back:1;
unsigned char charge_detect:1;
unsigned char sw_a:1;
unsigned char sw_b:1;
short no;
int id;
char name[];
};
int main()
{
printf("sizeof int is %ld\n", sizeof(int));
printf("sizeof struct student is %ld\n", sizeof(struct student));
#if 0 // error: invalid use of flexible array member: st.name =(char *)malloc(6);
struct student st;
st.no = 1;
st.id = 1;
st.name =(char *)malloc(6);
if(st.name == NULL){
printf("malloc error!\n");
exit(-1);
}
strcpy(st.name, "WORLD");
printf("st.no[%d], st.id[%d], st.name[%s]\n", st.no, st.id, st.name);
#endif
struct student *pst;
int ssize = sizeof(struct student) + 6*sizeof(char);
// pst = (struct student*)malloc(sizeof(struct student) + 6*sizeof(char));
pst = (struct student*)malloc(ssize);
if(pst == NULL){
printf("malloc error!\n");
exit(-1);
}
pst->no = 1;
pst->id = 1;
pst->anticollision_front=0;
pst->anticollision_back=1;
pst->charge_detect = 1;
pst->sw_a = 0;
pst->sw_b = 1;
strcpy(pst->name, "WORLD");
printf("pst->no[%d], pst->id[%d], pst->name[%s]\n", pst->no, pst->id, pst->name);
printf("pst->anticollision_front[%u], pst->anticollision_back[%u], pst->charge_detect[%u],
pst->sw_a[%u], pst->sw_b[%u]\n", pst->anticollision_front, pst->anticollision_back,
pst->charge_detect, pst->sw_a, pst->sw_b);
printf("sizeof struct student is %ld\n", sizeof(struct student));
int i;
char *pc = (char *)pst;
for(i = 0; i <ssize;){
printf("%.2X ", (char)pc[i]&0xFF);
i++;
}
printf("\n");
struct student *pst1 = (struct student*)malloc(ssize);
if(pst1 == NULL){
printf("malloc error!\n");
exit(-1);
}
memcpy(pst1, pst, ssize);
pc = (char *)pst1;
for(i = 0; i <ssize;){
printf("%.2X ", (char)pc[i]&0xFF);
i++;
}
printf("\n");
free(pst);
free(pst1);
return 0;
}
3. 位域
有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。
定义
位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:
struct 位域结构名
{
位域列表
};
其中位域列表的形式为: 类型说明符 位域名:位域长度
例如:
struct bs
{
int a:8;
int b:2;
int c:6;
};
注意
对于位域的定义尚有以下几点说明:
- 一个位域必须存储在同一个字节中,不能跨两个字节。
如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:
struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*从下一单元开始存放*/
unsigned c:4
}
这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。
- 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:
struct k
{
int a:1
int :2 /*该2位不能使用*/
int b:3
int c:2
};
从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。
也就是说后面加上“:1”的意思是这个成员的大小占所定义类型的1 bit,“:2”占2 bit,依次类推。当然大小不能超过所定义类型包含的总bit数。
参考:结构体中冒号--位域