精华内容
下载资源
问答
  • 一般形式 语法形式 运行结果 ... 变量或表达式所属类型占的内存字节数 实例 #include<stdio.h> int main(){ int a; double b; char c; printf("sizeof(int)=...

    一般形式

    语法形式 运行结果
    sizeof(类型) 类型占用的内存字节数
    sizeof(变量或表达式) 变量或表达式所属类型占的内存字节数

    实例

    #include<stdio.h>
    int main(){
        int a;
        double b;
        char c;
        printf("sizeof(int)=%d\n",sizeof(a));
        printf("sizeof(double)=%d\n",sizeof(b));
        printf("sizeof(char)=%d\n",sizeof(c));
        printf("sizeof(char + double)=%d\n",sizeof(c)+sizeof(b));
    } 

    输出结果

    sizeof(int)=4
    sizeof(double)=8
    sizeof(char)=1
    sizeof(char + double)=9

    我的微信公众号

    SouthEast

    展开全文
  • 如果不考虑或者不存在内存对齐问题,这个结构体应该1+4+1 = 6个字节,然而事实上它了12个字节,???,这就涉及到内存对齐问题了。 结构体中成员可以是不同数据类型,成员按照定义时顺序依次存储在连续...

        1. 结构体对齐问题

    struct S
    {
    	char a;
    	int b;
    	char c;
    };
    

    如果不考虑或者不存在内存对齐问题,这个结构体应该占1+4+1 = 6个字节,然而事实上它占了12个字节,???,这就涉及到内存对齐问题了。

    结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间,和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题

    2. 如何对齐的

     VS编译器默认对齐(#pragma pack(n))的数值是8  linux下默认是4。

    2.1 自然对界

    struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float 等)的变量,也可以是一些复合数据类型(如array、struct、union 等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
    【注】自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size 最大的成员对齐。注:这里的最大指整形数据,实型,结构体成员不在此例。见后面实例程序。

    (1)存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:

    (1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)(自然对界)、或者必须是指定对界的整数倍。
    (2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数(自然对界)、或者指定对界的整数倍。

    (2) 对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:

    (1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
    (2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。

        2.2 指定对界

    一般地,可以通过下面的方法来改变缺省的对界条件:

    • 使用伪指令#pragma pack (n),编译器将按照n 个字节对齐;
    • 使用伪指令#pragma pack (),取消自定义字节对齐方式。

    【注】如果#pragma pack (n)中指定的n 大于结构体中最大成员的size,则其不起作用,结构体仍然按照size 最大的成员进行对界。
     

    另外,GCC还有如下的一种方式:

    __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
    __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
     

    (1)存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:

    (1)结构体变量中成员的偏移量必须是指定对界和成员大小相比较小的那个值的整数倍。
    (2)结构体大小必须是指定对界和成员大小相比较小的那个值的整数倍。

    (2) 对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:

    (1)展开后的结构体的第一个成员的偏移量应当是指定对界和成员大小相比较小的那个值的整数倍。
    (2)结构体大小必须是指定对界和成员大小相比较小的那个值的整数倍。

    3. 例子

    3.1 自然对界

    例一

    struct S1
    {
        char c1;
        char c2;
        int i;
    };
    printf("%d\n", sizeof(struct S1));

    结果是8,我们来分析一下为什么结果是 8??

    • c1是char型,占一个字节,第一个成员即 c1 在结构体变量偏移量为0 的地址处。
    • c2是char型,占一个字节,要对齐到对齐数的整数倍的位置,char类型的对齐数是1,所以对齐到1 的整数倍,那就是偏移量为1开始的地址空间。
    • i是int类型,占四个字节,要对齐到对齐数的整数倍的位置。int类型的对齐数就是 4,所以对齐到4 的整数倍,前面两个c1和c2占两个字节,所以得补两个字节,使得i之前为4字节就可以了。

    我们来看一下内存分布图:

    例二

    struct S2
    {
        char c1;
        int i;
        char c2;
    };
    printf("%d\n", sizeof(struct S2));

    结果是12,来看一下过程?

    • c1是char型,占一个字节,对应到结构体变量偏移量为0 的地址处。
    • i是int型,占四个字节,对齐数就是4,对齐到4的整数倍位置处,即偏移量为4开始的地址空间,那c1后面有三个字节是不用的。
    • c2是char型,占一个字节,对齐到1 的整数倍,那就是下一个地址空间,对齐到偏移量为8的地址空间。

    但是整个结构体为了整体对齐,得是4的整数倍,所以c2后面补三个字节,那么总大小就是12个字节空间。所以输出结果是12。

    看一下内存分布图:

    例三

    struct S3
    {
        double d;
        char c;
        int i;
    };
    struct S4
    {
        char c1;
        struct S3 s3;
        double d;
    };
    printf("%d\n", sizeof(struct S4));

    结果是32,分析:
    struct S3占16个字节。(8、1+3、4)
    struct S4中有三个成员变量:

    • 第一个char型,占一个字节,对齐到偏移量为0的地址处。
    • 第二个成员是结构体嵌套使用,刚才已经得出占16个字节,计算对齐数要拆开结构体来看, d为8字节,所以c1补7字节。
    • 第三个成员是double型,占8个字节,前面是1+7和16,共24,是8的整数倍,所以对应偏移量24的地址处。
    • 整体看一下,32字节,也是最大成员8字节的整数倍,OK。

    所以是32。

    3.2 指定对界

    例一

    #pragma pack(2)
    
    struct S1
    {
        char c1;
        char c2;
        int i;
    };
    printf("%d\n", sizeof(struct S1));

     指定为2字节对齐,结构体大小为6字节。

    •  第一个c1一字节,偏移0;
    • 第二个c2一字节,指定对界为2字节,成员只有1字节,直接偏移1字节就行。
    • 第三个i为四字节,指定对界为2字节,成员自己数4字节更大,按照2字节对齐,前面正好2个字节,所以偏移2字节就好。这个4字节会被分成两段存储,那么我们取该变量值时就得从内存中取两次,或多或少降低了效率,也是所说的用时间换空间。
    • 总的看一下,6字节,是2的整倍数。

    例二

    #pragma pack(2)
    struct S2
    {
        char c1;
        int i;
        char c2;
    };
    printf("%d\n", sizeof(struct S2));

     指定为2字节对齐,结构体大小为8字节。

    •  第一个c1一字节,偏移0;
    • 第二个i 四字节,按照2字节对齐,前面只有1字节,得补1字节,所以偏移2,并且分为两段。
    • 第三个c2一字节,指定对界为2字节,前面6个字节,紧挨着放就可以了,偏移6。
    • 总的看一下,7字节,不是2的整倍数,最后面补1位。

    总共占8字节。

    4. 总结

    • 如果没有指定对界,那我们就看成员,每个成员安排存储空间时,看之前的空间大小是否是自己大小的整数倍,不是就补。最后结构体大小取决于最大的成员的大小,得是最大成员大小的整数倍。
    • 当指定了对界,如果指定的对界大于所有成员的大小,那其实是不起作用的,就相当于未指定对界;
    • 当指定了对界,如果结构体存在成员大小是大于对界大小的,那么我们指定的对界值才有意义,且存在的这个成员得分段存储。即小于对界值的成员按照自己大小整数倍偏移,大于对界值的按对界值整数倍偏移,最终结构体大小就是是指定对界的整数倍。

    5. 为什么存在内存对齐呢?

    (1)平台原因(移植原因):
    不是所有的硬件平台都能访问任意地址的任意数据的;某些平台只能在某些地址处取某些特定类型的数据

    (2)性能原因:
    数据结构尤其是栈应该尽可能在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次访问内存;而对齐的内存访问仅需要一次访问。

    缺点:无可厚非:这必然会存在效率问题,这是一种以空间换时间的做法,但这种做法是值得的

     

     

    展开全文
  • C语言中有一个专门用于检测类型或变量或数组在内存中所占有的空间(字节数)的操作符sizeof,用它可以直接检测出数组在内存占有的字节数。语法规则是:sizeof(x);(识别没有歧义时也可写成sizeof x;)——其中x是类型名...

    C语言中有一个专门用于检测类型或变量或数组在内存中所占有的空间(字节数)的操作符sizeof,用它可以直接检测出数组在内存占有的字节数。语法规则是:sizeof(x);(识别没有歧义时也可写成sizeof x;)——其中x是类型名、变量名或数组名等,返回x所占字节数(int型)。以下代码可以帮助理解:

     1 #include "stdio.h"
     2 struct X{
     3     int d;
     4     float t;
     5     double b;
     6     char n[100];
     7 };
     8 int main(int argc,char *argv[]){
     9     int a[]={1,2,3,4,5,6,7,8,9,10};
    10     double y=3.1415926;
    11     struct X t[3]={{0,0.0f,0.0,""},};//结构体数组属复杂类型
    12     printf("10 elements of int array needs %d bytes.\n",sizeof a);//检测整型数组
    13     printf("Double variables of type need %d bytes.\n",sizeof(y));//double类型变量
    14     printf("Type float need %d bytes.\n",sizeof(float));//float类型
    15     printf("Structure array 't[3]' need %d bytes.\n",sizeof t);//检测复杂类型
    16     return 0;
    17 }

     

    转载于:https://www.cnblogs.com/liangbo-1024/p/9212983.html

    展开全文
  • C 语言的结构体可以将不同类型的对象聚合到一个对象中,在内存中,编译器按照...如果要计算结构体中某成员相对于该结构体首地址的偏移量,一般第一个反应就是该成员的地址与结构体对象的首地址之间的字节数。 typedef
    • C 语言的结构体可以将不同类型的对象聚合到一个对象中,在内存中,编译器按照成员列表顺序分别为每个结构体变量成员分配内存,但由于 C 的内存对齐机制以及不同机器间的差异,各个成员之间可能会有间隙,所以不能简单的通过成员类型所占的字长来推断其它成员或结构体对象的地址。

    • 如果要计算结构体中某成员相对于该结构体首地址的偏移量,一般第一个反应就是该成员的地址与结构体对象的首地址之间的字节数。
      这里写图片描述

    typedef struct _tTask {
        tTaskStack * stack;
        uint32_t delayTicks;
        // 延时结点:通过delayNode就可以将tTask放置到延时队列中
        tNode delayNode;
        uint32_t prio;
        uint32_t state;
     }tTask;
    
    // tinyOS链表的结点类型
    typedef struct _tNode
    {
        struct _tNode * preNode;
        struct _tNode * nextNode;
    }tNode;
    
    #define tNodeParent(node, parent, name) (parent *)((uint32_t)node - (uint32_t)&((parent *)0)->name)
    
    tNode * node;
    
    // 检查所有任务的delayTicks数,如果不0的话,减1。
    for (node = tTaskDelayedList.headNode.nextNode; node != &(tTaskDelayedList.headNode); node = node->nextNode)
    {
        tTask * task = tNodeParent(node, tTask, delayNode);
        if (--task->delayTicks == 0) 
        {
            // 将任务从延时队列中移除
            tTimeTaskWakeUp(task);
    
            // 将任务恢复到就绪状态
            tTaskSchedRdy(task);            
        }
    }
    1. 一个parent代表结构体的类型,name代表结构体中的成员。
    2. ((parent*)0),把数字0强制转换成parent 结构体指针类型。这样 ((parent )0) 这个整体就相当于一个指针指向了 0 这个地址,不管 0 这个地址是否合法,是否真的有这么一个结构体对象,它都会把以 0 地址为首的一片连续内存当成一个结构体对象操作。
    3. ((parent*)0)->name,结构体指针((parent*)0)取结构体对象中name成员。因为这只是对内存操作,并没有写内存,虽然地址不合法也不会出现段错误。
    4. &((parent *)0)->name对name成员取地址。
    5. offset = (uint32_t)&((parent *)0)->name偏移量。因为这个parent类型结构体对象是从0地址开始的,故而offset就是成员name的偏移量。

    知道成员偏移量,就很容易求结构体对象本身的地址。成员的地址减去偏移量就是是结构体对象的首地址!
    ((parent*)0)((uint32_t)node - (uint32_t)&((parent*)0)->name)结构体对象的首地址,即任务控制块。

    展开全文
  • 例如:一个 int 型的变量,所4个字节空间,那么数据在空间里如何存储呢? 原码、反码、补码 计算机中有符号,有三种表示方法,即:原码、反码、补码。 这三种表示方法都有 符号位 和 数值位。 符号位:用 0
  • 如何计算结构体类型所占内存的字节数? 在计算结构体类型所占内存的字节数时,不能用结构体的每个成员类型所占内存字节数的“和”作为一个结构体实际所占的内存字节数。 对多数计算机系统而言,为了提高内存寻址的...
  • 2.3数据类型

    2020-03-06 17:33:09
    2.4如何计算变量或者数据类型所占内存空间的大小 /* 一个字节(Byte)由8个二进制位(bit)构成 同种类型的数据在不同的编译器或者计算机系统中所占的字节数不同,需要使用sizeof()运算符,sizeof是关键字,不是函数...
  • c语言数组长度问题

    2017-10-25 22:26:00
    c语言中定义一个数组,如何获取数组长度有时是我们必须所用到。...sizeof计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示(当然用在字符数组计算"\0"大小)。 举例:{ int a[5]={1,...
  • 一个订单假设会产生1KB的对象(估计方法:这个对象内包含哪些声明的变量,在这个对象内会嵌套哪些对象挖到最内层计算变量占的字节数,从而来预估每个对象所内存大小),每秒钟就会产生3...
  • //定义变量计算图像每行像素所占的字节数(必须是4的倍数) int lineByte=(bmpWidth*biBitCount/8+3)/4*4;//灰度图像有颜色表,且颜色表项为256 if(biBitCount==8) { //申请颜色表所需要的空间,读颜色表进内存 ...
  • 内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的...
  • 中文和英文字符所占的字节数是一样的吗 如何统计一段中英文混合字符的字符数 排序法都有哪些,其算法都是怎样的 如何将十进制字符串、十六进制字符串和二进制字符串互相转化 如何随机选号 第15章 发布程序 如何给...
  • c++ 面试题 总结

    2009-09-16 08:44:40
    代码的位置必须在物理内存中才能被运行,由于现在的操作系统中有非常多的程序运行着,内存中不能够完全放下,所以引出了虚拟内存的概念。把哪些不常用的程序片断就放入虚拟内存,当需要用到它的时候在load入主存...
  • 137_指针17_何谓变量的地址 一个指针变量到底几个字节【难点】 136_指针16_指针变量的运算 135_指针15_复习上节课知识 134_指针14_确定一个一维数组需要2个参数及其原因_下 134_指针14_确定一个一维数组需要2个...
  • 1.形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。 2.实参可以是常量、变量、表达式、函数...
  • 看到网上有个方案说:主项目负责加载组件,由于主项目和组件之间是隔离,那么主项目如何调用组件ApplicationLike生命周期方法呢,目前采用是基于编译期字节码插入方式,扫描所有ApplicationLike类(其有一...
  • 经过跟踪变量值发现循环变量i阀值pSysHead->dbf_count数值为0xFFFFFFFF,该值是从被破坏的内存数据库中获取,正常情况下该值小于127。而pDBFat是数据库起始地址,如果pSysHead->dbf_count值异常过大,将...
  • 功能主要有内存的分配和管理、内存的扩充技术、内存保护技术 2、分区分配存储管理 分为固定分区、可变分区、可重定位分区、多重分区。 内存“扩充”技术: •交换:由操作系统做,用户不知道。 ...
  • java 面试题 总结

    2009-09-16 08:45:34
    内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的...
  • 编程显示你使用的计算机中的各种数据类型的字节数。 解: 源程序: #include <iostream.h> int main() { cout (int) ; cout (short) ; cout (long) ; cout (char) ; cout (float) ; cout (double) ; return 0; } ...
  • 但是实际情况往往是,这些书中忽略掉内容恰恰去了一个初学者大部分时间,甚至影响了学习热情。 我至今仍记得当我开始编写自己操作系统时所遭受挫败感,那是一种不知道如何着手无助感觉。还好我坚持...
  • 但是实际情况往往是,这些书中忽略掉内容恰恰去了一个初学者大部分时间,甚至影响了学习热情。 我至今仍记得当我开始编写自己操作系统时所遭受挫败感,那是一种不知道如何着手无助感觉。还好我坚持...
  • 入门学习Linux常用必会60个命令实例详解doc/txt

    千次下载 热门讨论 2011-06-09 00:08:45
    文件为doc版,可自行转成txt,在手机上看挺好。 本资源来自网络,如有纰漏还请告知,如觉得还不错,请留言告知后来人,谢谢!!!!! 入门学习Linux常用必会60个命令实例详解 Linux必学60个命令 Linux提供...
  • IVD:超过20/20微观数据维变量等级文件 IVP:超过20/20用户子集配置文件 IVT:超过20/20表或集合数据文件 IVX:超过20/20微数据目录文件 IW:Idlewild屏幕保护程序 IWC:Install Watch文档 J J62:...

空空如也

空空如也

1 2
收藏数 26
精华内容 10
关键字:

如何计算变量占内存的字节数