结构体的概念 方法 例题 匿名结构体 自引用 结构体内存对齐原因,方法及如何修改默认对齐数

简介: 结构体的概念 方法 例题 匿名结构体 自引用 结构体内存对齐原因,方法及如何修改默认对齐数
#include<stdio.h>
//结构体
//数组是一组相同类型的元素的集合,结构体也是一些值的集合,但是结构的每个成员可以是不同类型
//struct Book                 //b1,b2,b3,b4,b5,b6都是创建的变量
//{
//    char name[20];
//    int price;
//    char id[12];
//}b4,b5,b6;//全局变量
//int main()
//{
//    struct Book b1;
//    struct Book b2;//局部变量b1,b2,b3
//    struct Book b3;
//    return 0;
//}


声明时,可以不完全声明,如


//struct//匿名结构体类型(创建变量s)
//{
//    char c;
//    int i;
//    char ch;
//    double d;
//}s;


但是下面这种,在编译器角度是不对的,因为是两种不同的类型


//struct
//{
//    char c;
//    int i;
//    char ch;
//    double d;
//}s;
//struct
//{
//    char c;
//    int i;
//    char ch;
//    double d;
//}*ps;
//int main()
//{
//    ps = &s;
//    return 0;
//}
//结构体自引用
//struct Node//Node不能省略(不能匿名),因为此处的Node(名字)要放下一个结构体的指针
//{
//    int data;//定义数据
//    struct Node* next;//把下一个结构体的地址放在该结构体中
//    //在结构体里,不是包含同类型的结构体变量,而是包含同类型的结构体指针
//};
//int main()
//{
//    //struct N sn;是错误的,结构体不能自己包含自己
//    //在结构体里,不是包含同类型的结构体变量,而是包含同类型的结构体指针
//    return 0;
//
//}
//struct S
//{
//    char c;
//    int i;
//
//}s1,s2;
//struct B
//{
//    double d;
//    struct S s;
//    char c;
//};
//int main()
//{
//    struct B sb = { 3.14,{'w',100},'q' };// 3.140000 w 100 q
//    //结构体操作符有    .  和   ->
//    printf("%lf %c %d %c", sb.d, sb.s.c, sb.s.i, sb.c);
//    return 0;
//}
//struct S
//{
//    char c1;
//    int i;
//    char c2;
//};
//struct S2
//{
//    char c1;
//    int i;
//    double d;
//};
//struct S3
//{
//    char c1;
//    char c2;
//    int i;
//};
//struct S4
//{
//    double d;
//    char c;
//    int i;
//};
//struct S5
//{
//    char c1;
//    struct S4 s4;
//    double d;
//};
//struct S6
//{
//    char n;
//    int m;
//};
//struct S7
//{
//    int  n;
//    char m;
//};


结构体内存对齐

1.结构体的第一个成员永远都放在结构体变量在内存中存储位置的10偏移处开始

2.从第2个成员往后的所有成员,都放在上一个成员的最小倍数的整数倍的地址处

(如char c int i放置为0~3(1-3浪费掉,但是必须是int的最小倍数4倍)4~7)

(如果是上一个结构体类型,就浪费掉上一个结构体距离最近的类型的最小倍数)---参见s5

3.结构体的总大小是结构体的所有成员的对齐数的整数倍

注意:放在前放在后都一样


//int main()
//{
//    struct S s = { 0 };
//    printf("%d\n", sizeof(s));//12   0~3(1-3为浪费掉,下一个int为4)+4~7+8~11(9-11浪费掉)=12个
//    struct S2 s2 = { 0 };
//    printf("%d\n", sizeof(s2));//12  0~3(1-3为浪费掉,下一个int为4)+4~7+8~15=16个
//    struct S3 s3 = { 0 };
//    printf("%d\n", sizeof(s3));//8   
//    //0(下一个char为1,是倍数,不需要浪费)+1~4(2-4为浪费掉,下一个int为4)+5~7=8个
//    struct S4 s4 = { 0 };
//    printf("%d\n", sizeof(s4));//16   0~7+8~11(9-11为浪费掉,下一个int为4)+12~15=16个
//    struct S5 s5 = { 0 };
//    printf("%d\n", sizeof(s5));//32  
//    //0~7(1-7为浪费掉,下一个S4里面的第一个是double,为8)+8~23+23~31=32个
//    struct S6 s6 = { 0 };
//    printf("%d\n", sizeof(s6));//8
//    struct S7 s7 = { 0 };
//    printf("%d\n", sizeof(s7));//8,放在前放在后都一样
//    return 0;
//}
//为什么存在内存对齐?
// 拿空间换时间
//1.平台问题:某些平台只能在某些地址访问特定类型的数据
//2.性能原因:访问未对齐的内存,需要访问两次,对其的内存,访问一次就可以
    //所以
//在设计结构体时,既要满足对齐,又要满足空间,需要:
//让空间小的尽量集中在一起
//当对齐方式不合适时,可以自己更改默认对齐数
//修改默认对齐数方法如下
//#pragma pack()
//#pragma pack(2)
//struct S
//{
//    char c1;
//    int i;
//    char c2;
//};
//#pragma pack(1)
//struct S2
//{
//    char c1;
//    int i;
//    char c2;
//};
//int main()
//{
//    printf("%d\n", sizeof(struct S));//8   2+4+2
//    printf("%d\n", sizeof(struct S2));//6  1+4+1
//    return 0;
//}


相关文章
|
12月前
|
编译器 C语言 C++
C/C++内存对齐规则(结构体、联合体、类)
C/C++内存对齐规则(结构体、联合体、类)
|
编译器 Linux C语言
什么是结构体和结构体的对齐规则
什么是结构体,为什么会用到结构体?C语言本身存在一些内置数据类型(比如int char float double 数组等),但这些不能满足我们的需要,我们创建了结构体来自定义自己需要的类型。
107 0
|
19天前
|
存储 NoSQL 编译器
如何检查结构体的对齐情况
在C/C++中,结构体的对齐情况会影响内存布局和访问效率。可以通过以下方法检查结构体的对齐情况:1. 使用 `sizeof` 操作符获取结构体大小;2. 使用 ` offsetof` 宏获取成员偏移量;3. 编译器提供的对齐属性或指令。
|
2月前
crash —— 如果知道结构体内部某个成员的地址,如何输出结构体内容?
crash —— 如果知道结构体内部某个成员的地址,如何输出结构体内容?
|
5月前
|
编译器 C语言 C++
结构体的详解(想要彻底了解结构体,那么看这一篇就够了!)
结构体的详解(想要彻底了解结构体,那么看这一篇就够了!)
|
5月前
|
存储 编译器 C语言
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一
57 2
|
5月前
|
编译器 Linux C语言
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二
51 1
|
6月前
结构体变量的定义以及与结构体变量调用的两种方式
结构体变量的定义以及与结构体变量调用的两种方式
89 0
|
C语言
【C语言】结构体 -- 结构体的声明 -- 定义和初始化 -- 成员的访问 -- 结构体传参
【C语言】结构体 -- 结构体的声明 -- 定义和初始化 -- 成员的访问 -- 结构体传参
|
编译器 C++
自定义类型之结构体的基础和进阶(有关位段、结构体自引用、嵌套、内存对齐、修改对齐数、结构体的传参、和offsetof宏的使用)
一、结构体基础知识 二、结构体的进阶(有关结构体的自引用,嵌套,内存对齐和内存设计) (一、)首先是结构体的嵌套 (二、)结构体的自引用 (三、)结构体的内存对齐(如何计算结构体的所占内存大小) (四、)如何修改默认对齐数 三、offsetof的意思 四、结构体的传参 五、位段的使用和注意 总结: