精华内容
下载资源
问答
  • 比较两个结构体信息中学生的成绩成员变量的大小,按照大小顺序输出。 参考代码: #include "stdio.h" #include "malloc.h" #include "string.h" #define NUM 1 struct STUDENT { ...
  • C语言定义了一个结构体怎么分配内存?C\C++中结构体变量与结构体指针内存分配问题? 问题1:结构体指针最开始怎么分配内存?用sizeof()是不能确定大小的。 问题2:给结构体变量分配之后,是否还要给每个成员分配,...

    C语言定义了一个结构体怎么分配内存?C\C++中结构体变量与结构体指针内存分配问题?


    问题1:结构体指针最开始怎么分配内存?用sizeof()是不能确定大小的。


    问题2:给结构体变量分配之后,是否还要给每个成员分配,还是只给不能确定大小的成员分配?


    问题3:如果是要每个成员分配内存,那么释放的时候是不是每个成员都要单独释放?指针加一之后,又怎么做?



    C\C++中结构体变量与结构体指针内存分配问题?


    (1)声明一个结构体变量,无论是否初始化,都开辟内存,声明一个结构体指针变量,对其初始化的时候才会开辟内存。


    (2)结构体变量分配结构体本身大小的空间,结构体指针分配4个字节,其实任何类型的指针都是分配四个字节的指针空间。


    (3)所以:
         A a[3]; //a里面是三个A变量,所以分配三个结构体大小
         A *a;  //a是一个指针,分配4个字节,就算A再大,a也只是4个字节,因为任何类型的指针都是4个字节。要使用a,必须先要对指针初始化,也即分配空间了。
         如:
         A *a;
         a = (A*)malloc(sizeof(A));


    (4)我们完全可以撇开结构体,把问题简单化成int类型来说明这个指针问题:
    int a1[10];
    int *a2;


    1)a1是包含10个int的数组,大小也就是10*sizeof(int)。直接使用a1不要在进行什么初始化或者分配空间的游戏,因为数组a1里面本身存放的就是int变量本身了。


    2)a2是一个int*的东西,也就是整型指针,a2不能存放int变量,它只能存放一个int变量的地址。如果要使用a2,必须首先对a2初始化,即将它指向一个int变量的地址,如:a2 = (int*)malloc(sizeof(int));
    或者
    int i = 10;
    a2 = &i;
    所以,malloc函数的作用是首先声明一个变量,然后返回该变量的地址。
    所以:a2 = (int*)malloc(sizeof(int)) 的含义就是把该变量的地址赋值给a2,和a = &i 本质上并没有什么不同,只是一个变量是栈上,一个是堆上,都是一个地址赋值。


    (5)所以,所谓的分配空间,就是对指针赋值,把一个变量的地址赋值给一个指针。

    展开全文
  • 一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。 声明一个...

    一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。

    声明一个结构体变量,无论是否初始化,都开辟内存,声明一个结构体指针变量,对其初始化的时候才会开辟内存。

    A a[3];  a是A型的,有3个,当然分配A乘3大小的空间

    A* a;    a是A*型的,当然只分配A*大小的空间,而不会分配A大小的空间

    结构体变量分配结构体本身大小的空间,结构体指针分配4个字节,其实任何类型的指针都是分配四个字节的指针空间。
    所以:
    A a[3]; //a里面是三个A变量,所以分配三个结构体大小
    A *a;  //a是一个指针,分配4个字节,就算A再大,a也只是4个字节,因为任何类型的指针都是4个字节。要使用a,必须先要对指针初始化,也即分配空间了。
    如:
    A *a;
    a = (A*)malloc(sizeof(A));

    我们完全可以撇开结构体,把问题简单化成int类型来说明这个指针问题:
    int a1[10];
    int *a2;

    很容易知道,a1是包含10个int的数组,大小也就是10*sizeof(int)。我们可以直接使用a1不用再进行什么初始化或者分配空间,因为数组a1里面本身存放的就是int变量本身了。

    然后a2,是一个int*的东西,也就是整型指针,a2不能存放int变量,它只能存放地址,一个int变量的地址。如果要使用a2,必须首先对a2初始化,即将它指向一个int变量的地址,如:
    a2 = (int*)malloc(sizeof(int));
    或者
    int i = 10;
    a2 = &i;
    所以,malloc函数的作用是首先声明一个变量,然后返回该变量的地址。
    所以:a2 = (int*)malloc(sizeof(int)) 的含义就是把该变量的地址赋值给a2,和a = &i 本质上并没有什么不同,只是一个变量是栈上,一个是堆上,都是一个地址赋值。
    【例7.3】指向结构体变量的指针的应用。

    1. #include <iostream>
    2. #include <string>
    3. using namespace std;
    4. int main( )
    5. {
    6. struct Student//声明结构体类型student
    7. {
    8. int num;
    9. string name;
    10. char sex;
    11. float score;
    12. };
    13. Student stu;//定义Student类型的变量stu
    14. Student *p=&stu;//定义p为指向Student类型数据的指针变量并指向stu
    15. stu.num=10301;//对stu中的成员赋值
    16. stu.name="Wang Fun";//对string变量可以直接赋值
    17. stu.sex='f';
    18. stu.score=89.5;
    19. cout<<stu. num<<" "<<stu.name<<" "<<stu.sex<<" "<<
    20. stu.score<<endl;
    21. cout<<p -> num<<" "<<(*p).name<<" "<<(*p).sex<<" "<<(*p).score<<endl;
    22. return 0;
    23. }
    程序运行结果如下:
    10301 Wang Fun f 89.5 (通过结构体变量名引用成员)
    10301 Wang Fun f 89.5 (通过指针引用结构体变量中的成员)
    两个cout语句输出的结果是相同的。

    为了使用方便和使之直观,C++提供了指向结构体变量的运算符->,例如p->num表示指针p当前指向的结构体变量中的成员num。
        p->num 和(*p).num等价。
    同样
        p->name等价于(*p).name。
    也就是说,以下3种形式等价:
    • 结构体变量.成员名。如stu.num。
    • (*p).成员名。如(*p).num。
    • p->成员名。如p->num。

    “->”称为指向运算符。

    请分析以下几种运算:
    • p->n 得到p指向的结构体变量中的成员n的值。
    • p->n++ 得到p指向的结构体变量中的成员n的值,用完该值后使它加1。
    • ++p->n 得到p指向的结构体变量中的成员n的值,并使之加1,然后再使用它。

    用结构体变量和指向结构体变量的指针构成链表

    链表是一种常见的重要的数据结构。图7.8表示最简单的一种链表(单向链表)的结构。


    图7.8

    链表有一个“头指针”变量,图中以head表示,它存放一个地址。该地址指向一个元素。链表中的每一个元素称为“结点”,每个结点都应包括两个部分:
    • 一是用户需要用的实际数据,
    • 二是下一个结点的地址。

    可以看到链表中各元素在内存中的存储单元可以是不连续的。要找某一元素,可以先找到上一个元素,根据它提供的下一元素地址找到下一个元素。

    可以看到,这种链表的数据结构,必须利用结构体变量和指针才能实现。

    可以声明一个结构体类型,包含两种成员,一种是用户需要用的实际数据,另一种是用来存放下一结点地址的指针变量。

    例如,可以设计这样一个结构体类型:
    1. struct Student
    2. {
    3. int num;
    4. float score;
    5. Student *next; //next指向Student结构体变量
    6. };
    其中成员num和score是用户需要用到的数据,相当于图7.8结点中的A, B, C, D。next是指针类型的成员,它指向Student类型数据(就是next所在的结构体类型)。用这种方法就可以建立链表。见图7.9。


    图7.9

    图中每一个结点都属于Student类型,在它的成员next中存放下一个结点的地址,程序设计者不必知道各结点的具体地址,只要保证能将下一个结点的地址放到前一结点的成员next中即可。

    下面通过一个例子来说明如何建立和输出一个简单链表。

    【例7.4】建立一个如图7.9所示的简单链表,它由3个学生数据的结点组成。输出各结点中的数据。
    1. #define NULL 0
    2. #include <iostream>
    3. using namespace std;
    4. struct Student
    5. {
    6. long num;
    7. float score;
    8. struct Student *next;
    9. };
    10. int main( )
    11. {
    12. Student a,b,c,*head,*p;
    13. a. num=31001;
    14. a.score=89.5; //对结点a的num和score成员赋值
    15. b. num=31003;
    16. b.score=90; //对结点b的num和score成员赋值
    17. c. num=31007;
    18. c.score=85; //对结点c的num和score成员赋值
    19. head=&a; //将结点a的起始地址赋给头指针head
    20. a.next=&b; //将结点b的起始地址赋给a结点的next成员
    21. b.next=&c; //将结点c的起始地址赋给b结点的next成员
    22. c.next=NULL; //结点的next成员不存放其他结点地址
    23. p=head; //使p指针指向a结点
    24. do
    25. {
    26. cout<<p->num<<" "<<p->score<<endl; //输出p指向的结点的数据
    27. p=p->next; //使p指向下一个结点
    28. } while (p!=NULL); //输出完c结点后p的值为NULL
    29. return 0;
    30. }
    本例是比较简单的,所有结点(结构体变量)都是在程序中定义的,不是临时开辟的,也不能用完后释放,这种链表称为静态链表。对各结点既可以通过上一个结点的next指针去访问,也可以直接通过结构体变量名a, b, c去访问。

    动态链表则是指各结点是可以随时插入和删除的,这些结点并没有变量名,只能先找到上一个结点,才能根据它提供的下一结点的地址找到下一个结点。只有提供第一个结点的地址,即头指针head,才能访问整个链表。如同一条铁链一样,一环扣一环,中间是不能断开的。

    建立动态链表,要用到后面介绍的动态分配内存的运算符new和动态撤销内存的运算符delete。

    用户栈是(运行时创建)是用户存放程序临时创建的局部变量,不包括静态变量,除此之外,在函数调用时,其参数也会被压入栈,并且带导函数调用结束后,函数的返回值也会存放到栈中。

    堆是用于存放程序进程中被动态分配的内存段,它的大小不固定,可动态扩展,结束后必须free掉。

    展开全文
  • 我们知道,struct结构体中可以有不同的数据类型变量,成员定义时依次存储在内存连续的空间,struct结构体变量的首地址就是第一个成员的地址,那么内存偏移量就是各个成员相对于结构体变量地址的...

    今天做到一道题目,题目是这样的:
    Alt
    这里考察了两个知识点:

    uinon结构体内存大小

    union变量所占的大小为成员中最大的那一个

    关于struct结构体的对齐问题

    参考了这篇博客struct结构体对齐问题
    我们知道,struct结构体中可以有不同的数据类型变量,成员定义时依次存储在内存连续的空间,struct结构体变量的首地址就是第一个成员的地址,那么内存偏移量就是各个成员相对于结构体变量地址的差(即相对于第一个成员地址的差)对于某个成员的内存偏移量,就为上一个成员的内存偏移量+上一个内存成员的大小

    那么另外我们需要了解的是对齐参数,系统默认的对齐参数由pack决定,每个成员的对齐参数为min(pack,成员类型大小),那么求出每个成员各自的对齐参数之后,那么结构体的对齐参数就为各个成员函数的对齐参数的最大值(也就是说,一个结构体的对齐参数最大也就为8),对齐参数的作用就是:对于每个成员的偏移量,需要能够被该成员的对齐参数整除,否则需要把该偏移量补齐到离他最近的对齐参数的倍数(对于偏移量为0,那么也是补齐为0)

    那么我们如何计算出一个结构体的实际大小呢,(1)从第一个成员出发,计算出该成员的内存偏移量(2)按照对齐参数来计算该成员的实际内存偏移量(3)依次按照上面的步骤计算出各个成员的实际内存偏移量(4)结构体的大小就为最后一个成员的大小+实际内存偏移量(5)结构体的实际大小就为按照对齐参数补齐得出的大小
    拿我们上面这个例子来说:

    (1)id的偏移量为0,按照它的对齐参数min(1,8)=0来补齐,所得的实际偏移量也是0
    (2)crc的偏移量0+1=1,按照它的对齐参数min(4,8)=4来补齐,那么它的实际偏移量就为4
    (3)pack的偏移量为1+4=5,按照它的对齐参数min(4,8)=4来补齐,那么它的实际偏移量就为8
    (4)结构体的大小为4+8=12
    (5)结构体的对齐参数为max(1,4,4)=4,按照结构体的对齐参数来补齐得到结构体的实际大小,那么也就是12(因为12能被4整除,所以不用补齐了)
    
    展开全文
  • 在C语言中,在默认情况下,编译器规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量...所以,在计算结构体变量的大小时: ①上面的所有字节数的总和,必须是下一个类型的整数倍数。 ②总字节...

     在C语言中,在默认情况下,编译器规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节的倍数。

    例如:

    struct MyStruct {

    double ddal;

    char dda;

    int type;

    };

    得到的结果为:16

     所以,在计算结构体变量的大小时:

     ①上面的所有字节数的总和,必须是下一个类型的整数倍数。

     ②总字节数一定是最大类型的整数倍。

     

    例题:

    char a;

    double b;

    int e;

    得:20

     

     

     

    转载于:https://www.cnblogs.com/LisaY/p/4665364.html

    展开全文
  • 结构体变量分配结构体本身大小的空间,结构体指针分配4个字节,其实任何类型指针都是分配四个字节指针空间。 所以: A a[3]; //a里面是三个A变量,所以分配三个结构体大小 A *a; //a是一个指针,分配4个字节,...
  • 1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除; 2. 结构体每成员相对于结构体首地址的偏移量都是当前成员大小的整数倍,如有需要编译器会在成员之间加上填充字节; 3. 结构体的总大小为结构体最...
  •  很多时候我们需要知道一个结构体成员中的某个成员的大小, 但是我们又不需要定义该结构体 类型的变量(定义的话会让人难以理解, 又没有实际的作用, 干嘛要定义?).  考虑可以用指针来反求, 比如有一个 POINT ...
  • 系列文章《C语言经典100例》持续创作中,欢迎大家关注和支持。喜欢同学记得点赞、转发、收藏哦~后续C语言经典100例将会以... 指向数组指针实现输出数组元素,定义一个指向数组指针用来灵活操作数组int a[1...
  • 声明一个结构体变量,无论是否初始化,都开辟内存,声明一个结构体指针变量,对其初始化时候才会开辟内存。 A a[3]; a是A型,有3个,当然分配A乘3大小的空间 A* a; a是A*型,当然只分配A*大小的空间,而...
  • 有时候我们想知道一个结构体变量的大小,如果是用sizeof操作只能在运行时才能知道结果。预处理是不计算sizeof大小的,因此使用预处理的方法行不通。 GCC编译器的一个告警给我们提供了方法: -Wlarger-than=len ...
  • struct 结构体类型的大小计算

    千次阅读 2017-11-30 21:09:49
    显然,结构体变量中第一个成员的地址就是结构体变量的首地址。 由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则: 一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍...
  • 结构体变量字节填充

    2017-10-21 17:46:00
    (1)sizeof也可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用。 (2)终于搞懂struct结构体内存分配问题了,结构体中各个成员字节对齐遵循以下几个原则: 直接用下面几个原则即可判断...
  • 章学完函数之后感觉对C语言基本能够看懂了,也明白C语言格式和书写方式...指针意思就是存储数据在内存中地址信息的变量,很饶口是不是,简单翻译一下,信息都是存储在内存中以字节为单位格子里,每...
  • 如何计算结构体对象的大小 今天在处理结构体对象的时候,... 结构体变量的起始地址能够被其最宽的成员大小整除 2. 结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节 3
  • sizeof(结构体)的大小

    千次阅读 2019-04-24 16:34:47
    由于系统存储结构体需要将结构体变量的地址对齐,并不是每变量根据自己的类型分配内存,所以结构里面变量不同的顺序会导致结构体的大小不同; 结构体大小计算: - 偏移量,结构体地址与结构体成员地址的差; - ...
  • VB.NET语言目前在自动化领域还有使用,如果一个多参数控制过程其中某一项需要“查稳态表”,并直接把稳态控制大小赋值给当前控制变量使用,如何实现?请看下面一种查TXT两列Double值判断前面一列大小近似...
  • 小议结构体的大小

    2015-03-24 21:50:56
    一个结构体所有成员都是同一类型,其大小当然好计算。下面主要讨论成员类型不一样情况结构体大小的计算。 对此,听说编译器有两条规则: 1、结构体变量中成员偏移量必须是成员大小的整数倍(0...
  • 结构体的大小

    2017-07-15 22:46:24
    结构体中的成员可以是不同的数据类型,成员按照定义时的...和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。看下面这样的一个结构体:  struct stu1  {
  • 结构体大小的计算

    2019-01-23 21:51:13
    结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是...显然,结构体变量中第一个成员的地址就是结构体变量的首地址,因此,第一个成员的偏...
  • 计算结构体的大小

    2021-01-14 11:42:19
    怎样计算一个结构体的大小呢? 先介绍一个概念——偏移量,结构体中的偏移量就是结构体成员和结构体变量的地址之差, 比如说第一个结构体成员的偏移量就是0,第二个结构成员的偏移量就是第一个结构
  • 结构体的大小 详析

    2016-11-17 18:16:29
    和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。看下面这样的一个结构体: struct stu1 {  int i;  char c;  int j; };  先介绍一个相关的...
  • 1、结构体变量中该成员的偏移量必须是该成员大小的整数倍(0被认为是任何数的整数倍) 2、结构体大小必须是所有成员大小的整数倍。 注意:1.先根据系统位数、编译器位数判定结构体中成员变量自身的大小;  2.该...
  • #define member_size(type, member) sizeof(((type *)0)->member) 说明如下: type:表示结构体类型名。 member:表示结构体成员变量名。 ...(type *) 0:0被强制转换...功能:计算一个结构体成员变量相对于结构..

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,111
精华内容 444
关键字:

一个结构体变量的大小