C语言---自定义类型:结构体(2)

简介: C语言---自定义类型:结构体

C语言---自定义类型:结构体(1)https://developer.aliyun.com/article/1544448

结构体对其的规则:

1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处

2.其他的成员变量要对齐到某个数字(对齐数)的整数倍的地址处

对齐数=编译器默认的一个对齐数与该成员变量大小的较小值

--vs中,默认对其的值是8

--Linux中qcc没有默认对齐数,对齐数就是成员自身的大小



3.结构体总大小为最大对齐数。(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)整数倍

4.如果嵌套了结构体的情况。嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整数大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍

//那么结构体是如何对齐的呢?
//结构体成员在内存中到底是怎么存放对齐的?
//那么我们就了解一下结构体对其的规则
 
 
 
//struct S1
//{
//    char c1;
//    char c2;
//    int n;
//};
//
//int main()
//{
//    struct S1 s1;
//
//    return 0;
//}
//1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
 
/*
2.对齐数=编译器默认的一个对齐数与该成员变量大小的较小值
 
--vs中,默认对其的值是8
 
*/
//在这个代码中,c1就是第一个成员,占一个字节,那么c1就占了内存中第0行的空间位置
//c2是1个字节,小于vs规定的对齐数8,所以c2要对齐在1的倍数的位置
//那么刚好1是1的倍数,那么c2就占了第1行的空间位置
 
//因为除了第一个成员,剩下的都是其他成员
 
//因为n的大小是4个字节,vs默认对齐数是8,4<8,那么c2的对齐数就是4
 
//所以n此时此刻要对齐在4的倍数上面,就是偏移量是4的倍数就行了
//所以我们是从第4行开始占的,占4个字节
 
//中间的2 3行是被空着的,因为这两个字节我们用不上了
 
 
/*
现在我们将所有成员都放进内存去了,占了8个字节
 
但是结构体的大小还不能因此判断
我们还要根据第三条进行判断
 
 
3.结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,
所有对齐数中最大的)的整数倍
 
 
这三个成员的默对齐数是最大对齐数是4,
那么在这里结构体的大小就是4的倍数,因为这里刚好8是4的倍数,所以我们直接进行判断结构体的大小是8个字节
 
*/
 
 
 
 
//对s2进行讲解
struct S2
{
 
    char c1;
    int n;
    char c2;
};
 
int main()
{
    struct S2 s2;
 
    return 0;
}
 
/*
根据规则
结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
因为c1占一个字节,那么c1就放在第一行的位置
 
对于n,n的大小是4个字节,vs上默认对齐数是8,因为4<8
那么取这两个数的较小数就是4作为n的对齐数,所以n要对齐4的倍数
那么我们就只能从第四行开始,因为是4个字节大小,所以从第4行到第7行都是n的范围
 
在这里我们又发现中间的1 2 3行是空的,说明我们又浪费三个字节
 
 
对于c2,因为c2的字节大小是1,vs默认对齐数是8,1<8,所以c2的对齐数是1
所以c2找到1的倍数就行了
 
刚好第8行是1的倍数,那么c2就将第8行占了
 
到目前为止S2占了9个字节了
但是真的是9个字节吗?
 
我们还得根据后面的规则进行判断
在S2中,最大的对齐数是4,那么结构体的总大小是4的倍数
但是9 10 11行都不是4的倍数,所以我们只能取第12行,
所以我们中间又浪费了3个字节的大小
所以最终S2结构体的大小是12
 
*/
struct S3
{
    double d;//0-7
    char c;//8
    int i;//10-12
    //最大对齐数是8,那么最后的位置固定在8的倍数上面,就是16
};
int main()
{
    printf("%d\n", sizeof(struct S3));//16
    return 0;
}
 
//因为double类型是8个字节,根据结构体对其的规则,构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
//那么0-就是d占了
 
/*
对于c来说,c大小1个字节,vs默认对齐数是8,因为1<8,所以c的对齐数是1
那么只要是1的倍数就行了
所以c就将第8行占了
 
 
对于i,i是4个字节,vs默认对齐数是8,4<8所以i的对齐数是4的倍数
所以 9 10 11这三块字节浪费了,直接从12开始,因为是4个字节大小,所以i的空间就是12-15行
 
因为这三个数据的最大对齐数是8,所以最后的结构体的大小要取8的倍数,,那么我们只能取16了
 
所以最后这个结构体大小就是16
 
*/
//练习4-结构体嵌套问题
struct S3
    {
        double d;
        char c;
        int i;
 
    };
 
 
struct S4
{
 char c1;
 struct S3 s3;
 double d;
};
int main()
{
    struct S4 s4;
    printf("%d\n", sizeof(struct S4));//32
    return 0;
}
 
/*
这种就是结构体嵌套了一种其他类型的结构体变量
 
我们在之前就将S3的大小算出来了,是16个字节的大小
S4成员c1因为是第一个成员,肯定是放在偏移量为0的地址处
因为c1类型是char类型,一个字节大小,所以第0行被c1占了
 
c1放完我们放s3
因为我们计算出的s3是16个字节,但是这个16个字节从哪里开始放呢?
 
 
根据规则4
如果嵌套了结构体的情况。嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,
结构体的整数大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍
 
所以s3要对齐到字节的结构体内最大对齐数8的整数倍处
 
所以s3对齐到8的倍数就行了,因为第一个8的倍数是8
所以s3是从第8行开始对齐的,因为大小是16个字节
 
所以s3占了8-23行
 
所以中间的1-7行的7个字节被浪费了 
 
对于d来说,因为类型是double,大小是8个字节,vs默认对齐数是8,
那么d的对齐数是8,所以d要对齐8的倍数位
因为24是8的对齐数,所以d从24行开始对齐,d的大小是8个字节
所以24-31行是d占了
 
现在我们已经占了32个字节了,从0-31行
那么32是不是我们最终的大小呢?
 
 
 
在规则4中我们还说到
结构体的整数大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍
 
因为这哥结构体所有成员中对齐数里面最大对齐数是8
并且我们结构的大小最终还是要取决最大对齐数的倍数,
因为最大对齐数的倍数是8
所以最终这个结构体的大小我们取32
 
*/

C语言---自定义类型:结构体(3)https://developer.aliyun.com/article/1544453

相关文章
|
3天前
|
编译器 测试技术 C语言
【C语言】:自定义类型:结构体的使用及其内存对齐
【C语言】:自定义类型:结构体的使用及其内存对齐
18 7
|
1天前
|
网络协议 编译器 Linux
结构体(C语言)
结构体(C语言)
|
2天前
|
编译器 C语言 C++
【海贼王编程冒险 - C语言海上篇】自定义类型:结构体,枚举,联合怎样定义?如何使用?
【海贼王编程冒险 - C语言海上篇】自定义类型:结构体,枚举,联合怎样定义?如何使用?
5 0
|
2天前
|
存储 编译器 Linux
【c语言】详解结构体
【c语言】详解结构体
5 0
|
6天前
|
编译器 C语言
C语言----自定义类型:联合和枚举
C语言----自定义类型:联合和枚举
|
6天前
|
C语言
C语言---自定义类型:结构体(4)
C语言---自定义类型:结构体
|
6天前
|
编译器 C语言
C语言---自定义类型:结构体(3)
C语言---自定义类型:结构体
|
10月前
|
存储 C语言
【C语言】 条件操作符 -- 逗号表达式 -- []下标访问操作符,()函数调用操作符 -- 常见关键字 -- 指针 -- 结构体
【C语言】 条件操作符 -- 逗号表达式 -- []下标访问操作符,()函数调用操作符 -- 常见关键字 -- 指针 -- 结构体
|
9月前
|
C语言
【C语言】——define和指针与结构体初识
【C语言】——define和指针与结构体初识
|
存储 C语言
C语言初识-关键字-操作符-指针-结构体
C语言初识-关键字-操作符-指针-结构体
47 0