关于C语言中的结构体所占的字节数 sizeof(struct)

C语言中的结构体所占的字节数 ,用sizeof求一个结构体的大小

C语言中用sizeof求结构体所占字节数的详细方法。

一、非嵌套结构体
    struct one{
        char a; // 1(char所占字节数) + 0(偏移量)
        short b; // 2(short所占字节数) + 2(偏移量)
        int c; // 4(int所占字节数) + 4(偏移量)
    };
    struct two{

        char a; // 1 + 0
        int c; // 4 + 4
        short b;// 2 + 8
    };
    struct three {
        unsigned int a; // 4 + 0
        int *p; //  8 + 8
        char b; // 1 + 16    注意 偏移量16是1的倍数,所以不用改。
    };
    printf("%d ,", sizeof (struct one));
    printf("%d ,", sizeof (struct two));
    printf("%d ", sizeof (struct three));

运行结果是:8 ,12 ,24
解析:
按理来说第一个应该是 1 + 2 + 4 = 7啊,第二个是 1 + 4 + 2 = 7,第三个是4 + 8 + 1 = 13。跟程序打印的完全不一样,这是应为C语言里面的字节对齐机制。
one结构体的char偏移量是0,第二个short b的偏移量等于它上一个变量的所占字节数加上偏移量即1(1 + 0),但是这个偏移量要是第二个变量b所占字节数的整形倍数,所以第一个偏移量由1变成2,然后第三个变量的偏移量等于第二个变量的所占字节数加上偏移量也就是4(2(short大小) + 2偏移量大小),所以最终的大小为最后一个变量的字节数加上第二个偏移量4,4+4=8,所以结构体one的所占字节数是8。
再来看two,偏移量刚开始是0,第二个变量的偏移量等于第一个变量的偏移量加上类型所占的字节数,也就是1,但是第二个变量是int,占4个字节,偏移量要是4的整数倍,所以由 1 -> 4 偏移量最终是4,第三个是short b,占两个字节,偏移量是 int(4) + 偏移量(4) 就是8,8是2的整数倍,不需要改变,所以就是 2 + 8,10个字节,最终的这个字节数要能够被这个结构体里面的字节数最大的类型整除,two这个结构体最大的是 int 4个字节。所以最终的结果由10变成12。
第三个思路也是一样,结果由17个字节转变成最终的24个字节。
规则就是:

	1. ***第一个变量的偏移量是0。***
	2. ***第二个变量的偏移量等于前面一个变量的类型所占字节数加上偏移量。***
	3. ***最终的字节数能够被这里面所占字节数最大的类型整除。***
二、嵌套结构体
    typedef struct{
        char a;
        struct
        {
            int *p;
        } kk;
        char c;
    }node1;
    typedef struct{
        char a;
        
        struct
        {
            int age;
            int *p;
        } kk;
        
        int b;
    }node2;

    printf("%d ,", sizeof (node1));
    printf("%d ,", sizeof (node2));

结果为:24 ,40 ,
首先来看第一个node1,结构体里面又嵌套了一个结构体,在这之前我看了网上的很多博客,看的是云里雾里的,简称”不说人话“。经过长达几个小时的折腾,最终找到了一些规律,用很多例子测试发现也是正确的。先由内到外一层一层的找,先找出内嵌结构体占字节数最大的类型,这个里面只有一个int p,占8个字节。然后在来看外面的,将外层的结构体分为两层,内嵌结构体上面的和下面的,将所有类型的字节数之和相加在除以这一整个结构体最大的类型(这里指的是前面提到的 int八个字节)在向上取整乘以最大的字节数,1除以8是零点几,向上取整后是1,在乘8 也就是8。然后是下半部分,只有一个int b,4个字节,4 / 8取整乘8也是8。外层两部分相加之后是16,内层这个结构按照前面的无嵌套结构体算就行了,就是8个字节。最后就是外层加内层 16 + 8 = 24个字节(这个结果也要满足是最大类型所占字节的倍数)。
第二个方式和上面一样。外层是 8 + 8 = 16个字节,内层是20个字节,外层加内层就是36个字节,这个结果不是最大字节数8的倍数,所以最终的结果是40。

END

本文只是个人的一些见解,有问题请在评论区指正!

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是完整的队列操作代码,包括驱动的初始化和退出函数: ``` #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> struct msg { int data; int complete; }; struct ring_buffer { int head; int tail; struct msg *data; int size; unsigned int capacity; }; struct ring_buffer *ring_buffer_init(unsigned int capacity) { struct ring_buffer *rbuf = kmalloc(sizeof(struct ring_buffer), GFP_KERNEL); rbuf->capacity = capacity; rbuf->head = rbuf->size = 0; rbuf->tail = capacity - 1; rbuf->data = kmalloc(rbuf->capacity * sizeof(struct msg), GFP_KERNEL); printk(KERN_DEBUG "ring_buffer create successfully!\n"); return rbuf; } int ring_buffer_is_empty(struct ring_buffer *rbuf) { return (rbuf->size == 0); } int ring_buffer_is_full(struct ring_buffer *rbuf) { return (rbuf->size == rbuf->capacity); } void ring_buffer_in(struct ring_buffer *rbuf, struct msg msg) { if (ring_buffer_is_full(rbuf)) { return; } rbuf->tail = (rbuf->tail + 1) % rbuf->capacity; rbuf->data[rbuf->tail] = msg; rbuf->size = rbuf->size + 1; } struct msg ring_buffer_out(struct ring_buffer *rbuf) { struct msg rsv_msg; if (ring_buffer_is_empty(rbuf)) { pr_info("buffer is empty!\n"); rsv_msg.complete = -1; return rsv_msg; } rsv_msg = rbuf->data[rbuf->head]; rbuf->head = (rbuf->head + 1) % rbuf->capacity; rbuf->size = rbuf->size - 1; return rsv_msg; } void destroy_ring_buffer(struct ring_buffer *rbuf) { kfree(rbuf->data); kfree(rbuf); } static int __init my_driver_init(void) { struct ring_buffer *rbuf = ring_buffer_init(10); struct msg msg1 = {1, 0}; struct msg msg2 = {2, 0}; struct msg msg3 = {3, 0}; ring_buffer_in(rbuf, msg1); ring_buffer_in(rbuf, msg2); ring_buffer_in(rbuf, msg3); struct msg out1 = ring_buffer_out(rbuf); struct msg out2 = ring_buffer_out(rbuf); struct msg out3 = ring_buffer_out(rbuf); printk(KERN_DEBUG "out1: %d, out2: %d, out3: %d\n", out1.data, out2.data, out3.data); destroy_ring_buffer(rbuf); return 0; } static void __exit my_driver_exit(void) { printk(KERN_DEBUG "my_driver exit\n"); } module_init(my_driver_init); module_exit(my_driver_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple example Linux module."); MODULE_VERSION("0.01"); ``` 上面的代码在驱动初始化函数创建了一个容量为 10 的环形队列,然后向队列插入了三个元素,接着连续地从队列取出三个元素并打印,最后在驱动退出函数销毁了队列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值