结构体

结构体

1. 结构体大小计算规则

| 第一个成员在结构体变量偏移为0的地址处
| 其他成员变量要对齐到某个数(对齐数)的整数倍的地址处
| 对齐数 = 编辑器默认的一个对齐数与该成员大小比较的较小的值
| 结构体总大小为最大对齐数(每种类型的成员变量都有一个对齐数)的整倍数
| 如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的大小就是所有的最大对齐数的整数倍
fafade9f738c425fc7944ff4679ec29c.png

更改默认对齐数

#pragma pack(n)//n为欲修改的对齐数

取消默认对齐数更改

#pragma pack()

示例

#pragma pack(4)
struct S{
	char a;
	char b;
	int c;
}
#pragmapack()

2. 结构体成员偏移量查看函数

size_t offsetof(structName,memberName)
头文件为:stddef.h

#include <stddef.h>
struct S1{
    char a;
    int b;
    char c;
};
int main(){
    printf("%d\n",offsetof(struct S1,a));//0
    printf("%d\n",offsetof(struct S1,b));//4
    printf("%d\n",offsetof(struct S1,c));//8
}

3. 结构体的函数初始化

struct S1{
    char a;
    int b;
};
void init(struct S1* s1){
    s1->a = 'c';
    s1->b = 1;
}
int main() {
    struct S1 s1 = {0};
    struct S1* ps1 = &s1;
    init(ps1);
    printf("%c %d\n",ps1->a,ps1->b);//c 1 
}

4. 位段

位段的作用是为了节省空间.

struct S{
	int a:2;
	int b:5;
	int c:10;
	int d:30;
}
int main(){
	printf("%d\n",sizeof(struct S))://8
	return 0;
}

如果用结构体开辟该类型成员的空间,需要16个字节,而用位段只需要8个字节。

4.1 空间开辟示意图

当位段为int类型时,成员的位段设定不能大于32.
07c39e3747bce6e5360ac9669a80dada.png

4.2 位段的跨平台问题

  1. int 位段被当成有符号数还是无符号数是不确定的
  2. 位段中最大位的数目是不能确定的。(16位机器最大16,32位机器最大32,大于16小于32的可以在32位运行,不能在16位运行)
  3. 位段中的成员在内存中是左到右还是右到左的分配标准也是未定义的
  4. 当一个结构包含多个位段,第一个位段所占用内存后剩余的内存不够第二个位段存储,那么该剩余的内存是浪费还是利用,也是不确定的

5. 枚举

enum Sex{
	MALE,  //0
	FEMALE, //1
	SECRET //2
};

5.1 自定义枚举成员常量值

enum Sex{
	MALE = 1,  //1
	FEMALE, //2
	SECRET //3
};

6. 柔性数组

结构体最后一个成员变量可以为不确定长度的数组。

  • 需要结合malloc( ),realloc( ),calloc( ) 函数进行使用柔性数组

6.1 代码示例

struct S{
	int a;
	int arr[]
};
int main(){
    //在未定义柔性数组的大小之前,存在柔性数组的结构体的大小是不包含柔性数组的
    //如:sizeof(struct S) == 4
    //结构体指针,malloc函数动态申请空间:结构体的空间以及柔性数组的空间(在申请时定义柔性数组的大小)
    struct S* ps = (struct S*) malloc(sizeof(struct S)+5*sizeof(int));
	/**
	/第二种方法:
	/
	/struct S{
	/int a;
	/int* arr
  / };
	/struct S* ps=(struct S*) malloc(sizeof(struct S));
	/ps->arr =(int* ) malloc(5*sizeof(int));
	*/
    //判断是否申请空间成功
    if(ps == NULL)
        return 0;
    //结构体成员变量赋值
    ps->a = 1;
    for (int i=0;i<5;i++)
        ps->arr[i] = i;
    //打印柔性数组
    for (int i=0;i<5;i++)
        printf("%d ",ps->arr[i]);
    //追加5个长度柔性数组:sizeof(struct S)+10*sizeof(int)==44
    struct S* pss = (struct S*) realloc(ps,44);
    if(pss != NULL)
        ps = pss;
    else
        return 0;
    //再次赋值柔性数组
    for (int i=5;i<10;i++)
        ps->arr[i] = i;
    //打印结构体
    printf("\n%d\n",ps->a);
    for (int i=0;i<10;i++)
        printf("%d ",ps->arr[i]);
    free(ps);
	   free(pss);
	   pss = NULL;
    ps = NULL;
    return 0;
}
posted @ 2022-06-16 22:05  青眼高歌  阅读(58)  评论(0)    收藏  举报