精华内容
下载资源
问答
  • 在说明一个结构体变量时系统分配给它的存储空间是 B 。 A) 该结构体中第一个成员所需存储空间 B) 该结构体中最后一个成员所需存储空间 C) 该结构体中占用最大存储空间的成员所需存储空间 D) 该结构体中所有成员...
  • 最近遇到一个问题,对全局的结构体变量进行赋值之后,再读取其中内容的时候发现Debug下是正常的,Release下不正常。 下面这个代码是可以重现这个问题的:一个全局的结构体变量主函数中对它进行赋值,然后...
  • 一个指针变量当用来指向一...结构指针变量说明的一般形式为: struct 结构名 *结构指针变量名例如,前面的例题中定义了stu这个结构,如要说明一个指向stu的指针变量pstu,可写为: struct stu *pstu;当然也可定...

    一个指针变量当用来指向一个结构变量时,称之为结构指针变量。结构指针变量中的值是所指向的结构变量的首地址。通过结构指针即可访问该结构变量,这与数组指针和函数指针的情况是相同的。

    结构指针变量说明的一般形式为:
        struct  结构名  *结构指针变量名

    例如,在前面的例题中定义了stu这个结构,如要说明一个指向stu的指针变量pstu,可写为:
        struct stu *pstu;
    当然也可在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构指针变量也必须要先赋值后才能使用。

    赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。如果boy是被说明为stu类型的结构变量,则:
        pstu=&boy
    是正确的,而:
        pstu=&stu
    是错误的

    结构名和结构变量是两个不同的概念,不能混淆。结构名只能表示一个结构形式,编译系统并不对它分配内存空间。只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。因此上面&stu这种写法是错误的,不可能去取一个结构名的首地址。有了结构指针变量,就能更方便地访问结构变量的各个成员。

    其访问的一般形式为:
        (*结构指针变量).成员名
    或为:
        结构指针变量->成员名
    例如:
        (*pstu).num
    或者:
        pstu->num
    应该注意(*pstu)两侧的括号不可少,因为成员符“.”的优先级高于“*”。如去掉括号写作*pstu.num则等效于*(pstu.num),这样,意义就完全不对了。下面通过例子来说明结构指针变量的具体说明和使用方法


    【例11-5】

     1 struct stu
     2 {
     3     int num;
     4     char *name;
     5     char sex;
     6     float score;
     7 } boy1={102,"Zhang ping",'M',78.5},*pstu;
     8 main()
     9 {
    10     pstu=&boy1;
    11     printf("Number=%d\nName=%s\n",boy1.num,boy1.name);
    12     printf("Sex=%c\nScore=%f\n\n",boy1.sex,boy1.score);
    13     printf("Number=%d\nName=%s\n",(*pstu).num,(*pstu).name);
    14     printf("Sex=%c\nScore=%f\n\n",(*pstu).sex,(*pstu).score);
    15     printf("Number=%d\nName=%s\n",pstu->num,pstu->name);
    16     printf("Sex=%c\nScore=%f\n\n",pstu->sex,pstu->score);
    17 }

     

    本例程序定义了一个结构stu,定义了stu类型结构变量boy1并作了初始化赋值,还定义了一个指向stu类型结构的指针变量pstu。在main函数中,pstu被赋予boy1的地址,因此pstu指向boy1。然后在printf语句内用三种形式输出boy1的各个成员值。从运行结果可以看出:
        结构变量.成员名
        (*结构指针变量).成员名
        结构指针变量->成员名
    这三种用于表示结构成员的形式是完全等效的。

    转载于:https://www.cnblogs.com/chunlanse2014/articles/4398258.html

    展开全文
  • 只有当某变量说明为这种类型的结构,才对该变量分配存储空间。  内存是以字节为单位编号,但一些硬件平台对某些特定类型的数据之恩能够从某些特定地址开始,比如从偶地址开始。若不按照适合其平台的要求对数据...

    ------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
    1、结构体存储原理

        结构名只能表示一个结构形式,编译系统并不对它分配内存空间。只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。

        内存是以字节为单位编号,但一些硬件平台对某些特定类型的数据之恩能够从某些特定地址开始,比如从偶地址开始。若不按照适合其平台的要求对数据存放进行对齐,会影响到效率。因此,在内存中,各类型的数据是按照一定的规则在内存中存放的,这就是对齐问题。

    结构体占用的内存空间是每个成员占用的字节数之和(考虑对齐问题)。

    2、结构体数据成员对齐的意义

        许多实际的计算机系统对基本类型数据在内存中存放的位置限制,它们会要求这些数据的起始地址的值是某个数K的倍数,这就是所谓的内存对齐,而这个K则被称为该数据类型的对齐模数(alignment modules)。

        这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。比如这么一种处理器,它每次读写内存的时候都从某8倍数的地址开始,一次读出或写入8个字节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个double类型数据就只需要一次内存操作。否则,我们可能需要两次内存操作才能完成这个动作,因为数据或许恰好横跨在两个符合对齐要求的8字节内存块上。

    3、结构体对齐的含义

    1)结构体总长度

    2)结构体内各数据成员的内存对齐,即数据成员相对结构体的起始位置

    4、结构体变量占用存储空间大小的计算方法和步骤

    1)将结构体内所有数据成员的长度相加,记为sum_a;

    2)将各数据成员为了内存对齐,按各自对齐模数而填充的字节数累加到和sum_a上,记为sum_b。对齐模数是#pragma pack指定的数值以及该数据成员自身长度中数值较小者。该数据相对起始位置应该是对齐模数的整数倍;

    3)将和sum_b向结构体模数对齐,该模数是#pragma pack指定的数值和结构体内部最大的基本数据类型成员长度中数值较小者。结构体的长度应该是该模数的整数倍。


    所谓“对齐在N上”,指定是“存放起始地址%N=0”


    #include <stdio.h>
    
    int main(int argc, const char * argv[]) {
        
        //计算结构体变量在内存中占用的字节数的方法
        //1)先找对齐模数
        //  对齐模数 是结构体中的基本数据类型中占用字节数最大的那个
        //          4
        //2)在计算结构体变量的中各个成员占用的字节和
        
        struct A{
        
            char ch[13];
            char ch1[11];
            int a;
       
        };
        //定义结构体变量
        struct A a1;
        printf("%ld\n",sizeof(a1));<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
        return 0;
    }
    结果为:28
    
    


    展开全文
  • C语言 struct结构体变量声明加冒号

    万次阅读 2014-07-15 16:45:11
    有些信息存储,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如存放一个开关量,只有0和1两种状态,用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为...

    有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有01两种状态,用一位二进位即可。

    为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为位域位段。所谓位域是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。

     

    1】定义:

    struct 位域结构名 
    {
    位域列表 };

     

    位域列表的形式类型说明符位域名:位域长度

     

    例如:

    structbs 
    {
     
    int a:8;
     
    int b:2;
     
    int c:6;
     
    }data;

     

    说明:databs变量,其中位域a8位,位域b2位,位域c6位。(一个字节8)

     

    2】位域可以无位域名,这时它只用来作填充或调整位置。

    无名的位域是不能使用的。

     

    例如:

    typedef  structk 
    {
     
    int  a:1
     
    int   :2     
     
    int  b:3
     
    int  c:2
     
    };

    从以上分析可以看出,位域在本质上就是一种结构类型,不过其成员是按二进位分配的。

     

    3】指针类型变量不能指定所占的位数

    这点很好理解,在c语言中,所有的指针类型统一占4字节,不能更改。

     

    4struct变量二进制位数简要说明

    例如:定义结构体如下:

    typedefstruct test

    {

    int                      a:2;

    unsigned int   b:2;

    };

    对于结构体test来说,ab成员都是占用两位二进制,但存储的最大值是不一样的。其中:a是有符号型,所以第一位用来存储符号,代表的最大值为二进制“+1”,即1b为无符号型,代表的最大值为二进制“11”,即3。此结构体占用的大小为4字节,而不是4位额!

    记住:位域成员不能单独被取sizeof,且给位域变量成员赋值时,当数值超过变量范围,自动截取不会报错!

     

    使用位域的主要目的是压缩存储,其大致规则为:
    1)
    如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字
    段将紧邻前一个字段存储,直到不能容纳为止;
    2)
    如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字
    段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

     

    示例1
    structBF1
    {
    char f1 : 3;
    char f2 : 4;
    char f3 : 5;
    };


    其内存布局为:
    |__f1___|____f2___ |__|____f3______|______|
    |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|

       位域类型为
    char,第1个字节仅能容纳下f1f2,所以f2被压缩到第1个字节中,而f3
    能从下一个字节开始。因此sizeof(BF1)的结果为2


    3)
    如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方
    式,Dev-C++采取压缩方式;

     

    示例2
    structBF2
    {
    char f1 :  3;
    short f2 : 4;
    char f3 :  5;
    };
    由于相邻位域类型不同,在VC6中其sizeof6,在Dev-C++中为2


    4)
    如果位域字段之间穿插着非位域字段,则不进行压缩;

     

    示例3
    structBF3
    {
    char f1 : 3;
    char f2;
    char f3 : 5;
    };
    非位域字段穿插在其中,不会产生压缩,在VC6Dev-C++中得到的大小均为3

     

    举这些例子是为了说明一下,定义位域的话,最好是把所以有位域放在一起,这样可以节省空间,另外也是为了强调一下位结构体的内存分配方式,按定义的先后顺序来分配


    5)
    整个结构体的总大小为最宽基本类型成员大小的整数倍!——永远成立!

    还是让我们来看看例子,你会感到不可思议:

     

    struct mybitfields
    {
    unsigned short a : 4;
    unsigned short b : 5;
    unsigned short c : 7;
    } test;
    => sizeof(test) ==2;

    struct mybitfields
    {
    unsigned char a : 4;
    unsigned char b : 5;
    unsigned char c : 7;
    } test;
    => sizeof(test) ==3;

    struct mybitfields
    {
    unsigned char a : 4;
    unsigned short b : 5;
    unsigned char c : 7;
    } test;
    => sizeof(test) ==6;

    struct mybitfields
    {
    unsigned short a : 4;
    unsigned char b : 5;
    unsigned char c : 7;
    } test;
    => sizeof(test) ==4;

    struct mybitfields
    {
    unsigned char a : 4;
    unsigned char b : 5;
    unsigned short c : 7;
    } test;
    => sizeof(test) ==4;

    struct mybitfields
    {
    unsigned char a : 4;
    unsigned int b : 5;
    unsigned short c : 7;
    } test;
    => sizeof(test) ==12;

     

    5】常用内置类型的字节数

    对于32位编译器来说:

    char      1个字节

    指针变量:   4个字节(32位的寻址空间是2^32,32bit,也就是4个字节。同理64位编译器)

    short int :  2个字节

    int        4个字节

    unsigned int :4个字节

    float:       4个字节

    double:      8个字节

    long:        4个字节

    long long:   8个字节

    unsigned long:4个字节

    展开全文
  • 一个程序,犯了一个低级错误,主要就是对于值传递与地址传递的概念理解不够深.下面我通过一个小实验例子加以说明其区别: 值传递:函数传值,形参会首先根据其定义类型开辟新的空间,并将其参数值复刻到新的内存...

    在写一个程序时,犯了一个低级错误,主要就是对于值传递与地址传递的概念理解不够深.下面我通过一个小实验例子加以说明其区别:
    值传递:函数传值时,形参会首先根据其定义类型开辟新的空间,并将其参数值复刻到新的内存空间中,新的内存空间开辟也就意味着其存储地址的改变,而函数中对其参数的操作,也只是对于新空间内操作,并不会对函数外,传的值作影响,即两个是完全不同的空间.
    地址传递:通常通过指针变量作为参数,由于指针变量是保存地址的变量,所以在通过指针变量去接收时,是传的地址,也就是说,在内存空间中,指向的是同一内存块,此时的操作会同时受到影响.

    需求:程序中,我想获取一结构体成员变量的地址,并由一个指针返回其成员变量地址,通过对指针值的修改,来影响其结构体成员变量的值.

    C语言:
    错的方式:

    #include<stdio.h>//输入输出
    typedef struct {
    	char a[10];
    }node, * nodes;
    
    void init(node b, char** m) {
    	printf("%p\n", &b);
    	*m = &(b.a[2]);
    }
    int main() {
    	node a = { "123456" };
    	char* n;
    	init(a, &n);
    	*n = '0';
    	printf("n=%c \na[2]=%c\n", *n, a.a[2]);
    	printf("%p\n", &a);
    	printf("%p\n", &(a.a[2]));
    	printf("%p\n", (&(&a)->a[2]));
    	printf("%p\n", n);
    }
    

    在这里插入图片描述
    从中可以看出:
    1.通过结构体对象.的方式获取成员变量地址和通过结构体指针->获取成员变量地址的方式获取到的地址是一样的,即两种方式获取无差别.
    2.结构体对象a作为实参传递到函数中由b接收,但可以看出其内存地址是不相同的,这也就跟值传递的机制有关.
    3.n作为指针返回的成员变量地址是基于复刻后的结构体变量b存在的,n和a[2]的地址是不同的.这也就导致最后对n指针的值修改,不影响其a结构体成员变量值.

    正确的方式:

    #include<stdio.h>//输入输出
    typedef struct {
    	char a[10];
    }node, * nodes;
    void init(node* b, char** m) {
    	printf("b内存地址:%p\n", b);
    	*m = &(b->a[2]);
    }
    int main() {
    	node a = { "123456" };
    	char* n;
    	init(&a, &n);
    	*n = '0';
    	printf("n=%c \na[2]=%c\n", *n, a.a[2]);
    	printf("a内存地址:%p\n", &a);
    	printf(" &(a.a[2])内存地址:%p\n", &(a.a[2]));
    	printf("(&(&a)->a[2])内存地址:%p\n", (&(&a)->a[2]));
    	printf("n内存地址:%p\n", n);
    }
    

    在这里插入图片描述

    从结果来看:
    我们通过n指针获取到了a[2]的地址,并通过对n指针指向的地址值的修改,影响了其a[2]的值.
    1.从内存地址看出,通过对a的指针传递(地址传递),由b接收,其a,b地址相同,然后n指针获取a[2]的地址并返回.

    展开全文
  • 结构体说明

    2020-03-02 11:29:16
    实际的问题中,组数据往往有不同的数据类型,例如,登记成绩,我们要记录各个学科的成绩,姓名,学号。这些信息分别用不同的数据类型来记录,会非常麻烦,为解决这问题,c++语言给出了种构造数据类型––...
  • 结构体

    2013-07-01 23:04:35
    结构体的类型声明方式为:  struct 结构体名 ...(2) 声明结构体类型,允许先声明过的结构体类型作另一个结构体类型的成员; 一、结构体变量定义有三种方法 (1) 先声明结构体类型,后定义变量
  • c语言结构体struct相关使用说明

    千次阅读 2018-01-15 11:21:26
    这段代码的含义是,声明一个无名(anonymous)的结构体,并创建了一个结构体变量point。如果这段声明是放在全局域(任意函数(比如main函数)外)内,那么point内的变量将被初始化为默认值,换句话说,以这种方式声明...
  • c语言结构体用法

    万次阅读 多人点赞 2018-10-08 15:43:51
    结构体(struct) 结构体是由基本数据... Turbo C中, 结构体也是种数据类型, 可以使用结构体变量, 因此, 像其它类型的变量一样, 使用结构体变量时要先对其定义。  定义结构体变量的一般格式为: stru...
  • 结构体指针作为函数参数,调用传递的是指向一个结构体变量的指针(即 结构体变量的地址);结构体变量作为函数参数,调用传递的结构体变量本身。 即一个结构体A,当它的指针作为参数传入函数func,那么...
  • C语言结构体用法

    2019-11-19 01:05:14
    结构体(struct) ... Turbo C中, 结构体也是种数据类型, 可以使用结构体变量, 因此, 像其它类型的变量一样, 使用结构体变量时要先对其定义。  定义结构体变量的一般格式为: struct 结构体...
  • C学习之结构体

    2015-09-13 19:53:00
    结构体(struct) 结构体是由基本数据类型... Turbo C中, 结构体也是种数据类型, 可以使用结构体变量, 因此, 像其它类型的变量一样, 使用结构体变量时要先对其定义。 定义结构体变量的一般格式为: struc...
  • 这段代码的含义是,声明一个无名(anonymous)的结构体,并创建了一个结构体变量point。如果这段声明是放在全局域(任意函数(比如main函数)外)内,那么point内的变量将被初始化为默认值,换句话说,以这种方式声明...
  • 结构体难点总结

    2017-10-24 22:52:07
    也可以定义结构体类型的同时定义结构体变量。 举例: // 定义类型的同时定义变量。 struct student { char name[20]; int age; }s1; // 将类型struct student重命名为s1,s1是一个类型
  • 运行一个结构体时,编译器需要给结构体中的每个变量成员分配内存空间,如这样一个结构体中  typedef struct A  {  char c1;  int i;  int j;  }A; 对其内存空间分配问题进行分析,如若不进行内存对齐...
  • 一个结构体变量定义完之后,其内存中的存储并不等于其所包含元素的宽度之和。 1.有两个原则: 原则一:结构体中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每一个...
  • 结构体是系列变量的组合,就像C++中的类,结构体的声明不会分配内存空间,故而使用需要定义结构体变量。 到这就会出现两基本问题,结构体变量如何定义;结构体变量分配的空间是多大。基于这两...
  • 结构体字节对齐

    2020-06-16 16:07:21
    3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会最末一个成员之后加上填充字节{trailing padding}。 对于以上规则的说明如下: 第一条:编译器结构体开辟空间,首先找到结构体
  • 枚举类型在结构体中占多少字节

    千次阅读 2019-06-14 21:13:01
    编译器突然在一个枚举类型的成员变量后面提醒字节未对齐。 于是,枚举类型在结构体中占多少字节这个问题就产生了。 一开始我以为它只占一个字节,结果我从上到下看了一下发现不对。 如果占一个字节说明这不会...
  • c语言结构体

    2012-09-13 12:06:00
    C语言,结构体(struct) 用法 结构(struct) 结构是由基本数据类型构成的、并用一个标识符来命名的各种变量的组合。 结构中可以使用不同的...类型的变量一样, 使用结构变量时要先对其定义。 定义结构变量的一...
  • sizeof 结构体大小-2

    2020-11-04 15:28:19
    简要说明:结构体成员按照定义时的顺序依次存储连续的内存空间,但是结构体的大小并不是简单的把所有成员大小相加,而是遵循一定的规则,需要考虑到系统存储结构体变量时的地址对齐问题。 、没有成员的...
  • 简要说明:结构体成员按照定义时的顺序依次存储连续的内存空间,但是结构体的大小并不是简单的把所有成员大小相加,而是遵循一定的规则,需要考虑到系统存储结构体变量时的地址对齐问题。 、没有成员的...
  • C++结构体计算小结

    2017-12-02 17:07:37
    阅读前,我要提出一个问题:存储变量时地址为什么要使用对齐。问的详细点,为什么要将各种类型数据按照一定的规则空间上排列,而不是顺序的一个一个的排放?一、原则由于存储变量时地址对齐的要求,编译器...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 286
精华内容 114
关键字:

在说明一个结构体变量时