精华内容
下载资源
问答
  • 设计程序时,最重要的步骤之一是选择表示数据的方法。 在许多情况下,简单变量甚至是数组还不够。为此,C提供了结构体变量提高表示数据的能力,它能让你创造新的...在结构体声明,用一对花括号括起来的是结构成...



    设计程序时,最重要的步骤之一是选择表示数据的方法。

    在许多情况下,简单变量甚至是数组还不够。为此,C提供了结构体变量提高表示数据的能力,它能让你创造新的形式。

    1、结构体 的定义

    struct book {		//book:结构体名
    	char 	title[40];		//成员
    	char 	author[40];		//成员
    	float 	price;			//成员
    };
    

    结构体声明中,用一对花括号括起来的是结构体成员列表,声明定义了结构体布局,其中【book】称为结构名,title、author、price称为成员
    右花括号后面的分号是声明所必需的,表示结体构布局定义结束。


    下面我们定义结构体变量

    struct	book 	HarryPotter;	//定义结构体变量 HarryPotter
    

    我们可以使用typedef简化结构体变量的定义,这里可以省略结构名【book】:

    typedef struct {
    	char 	title[40];		
    	char 	author[40];		
    	float 	price;			
    } BookCartoon;
    
    BookCartoon harryPotter;	//定义结构体变量 harryPotter
    

    我们操作【结构体变量】:

    harryPotter.title  = "Harry Potter";
    harryPotter.author = "J.K. Rowling";
    

    2、指向结构体 的指针

    定义指向结构体的指针:

    BookCartoon 	* pHarryPotter = &harryPotter;	//定义结构体指针 pHarryPotter
    
    pHarryPotter->title  = "Harry Potter";
    pHarryPotter->author = "J.K. Rowling";
    

    3、向函数 传递结构体的信息

    ANSI C允许把结构体作为参数使用。所以程序员可以选择是传递结构体本身,还是传递指向结构体指针

    GPIO_InitTypeDef	GPIO_InitStructure;
    
    GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_8;				 
    GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_Out_PP; 		 
    GPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz;
    
    GPIO_Init(GPIOA , &GPIO_InitStructure);		
    

    把指针作为参数的优缺点:
    (1)优点:执行起来很快,只需要传递一个地址;
    (2)缺点:无法保护数据。
    被调函数中的某些操作可能会意外影响原来结构中的数据。不过,ANSI C新增的const 限定符解决了这个问题。

    4、结构体的特性(结构体 赋值)

    现在的 C 允许把一个【结构体】赋值给另一个【结构体】,但是数组不能这样做。

    5、认识 共用体

    共用体union)是一种数据类型,它能在同一个内存空间中储存不同的数据类型(不是同时储存)。可以初始化共用体共用体只能储存一个值,这与结构体不同。

    union person {
    	int 	height;	//身高
    	double 	weight;	//体重
    };
    

    共用体变量:

    union person ZhangSan;	//张三
    union person Class[40];	//班级
    

    (1)第1个声明创建了一个单独的共用体变量ZhangSan,编译器分配足够的空间以便共用体变量能储存共用体声明中占用最大字节的类型:double类型。double类型占64位,即8字节。
    (2)第2个声明创建了一个数组Class,内含40个元素,每个元素都是8字节。

    展开全文
  • 结构体 union

    2011-06-08 20:55:27
    可通过指向共用体的指针变量引用共用体变量,引用形式为: 共用体指针变量-〉成员名 或 (*共用体指针变量).成员名 语句“union un *pu;pu=&un1;”之后,(*pu).c,pu ->k是合法的引用。 说明: 给共用体变量赋值时,...
    struct student {
    
    unsigned num; /* 学号 */
    char name[20]; /* 姓名 */
    char sex; /* 性别 */
    unsigned age; /* 年龄 */
    float score; /* 分数 */
    char addr[50]; /* 地址 */
    };


    struct date {
    int year, month, day;
    };
    struct student{
    unsigned num;
    char name[20];
    char sex;
    struct date birthday;
    float score;
    } stu1, stu2;

    注意{}不表示复合语句,其后有分号
    同一结构体的成员不能重名
    不同结构体的成员可以重名
    结构体成员和其他变量可以重名
    结构体类型与其成员或其他变量可重名
    struct test { int test; } test;
    结构体类型名称是struct 结构体名,注意struct关键字不能省略

    struct student stu[10], p=stu;
    ++p->num; /* 同++(p->num); */
    p++->num; /* 同(p++)->num; */


    变量的定义
    定义共用体类型的同时定义变量。
    先定义共用体类型,然后定义共用体变量。
    如果之后不再使用此共用体类型,可定义类型时省略共用体名并同时定义变量。
    union example
    {char c1;
    int c2;
    float c3;
    }un1,un2;

    变量的引用
    引用共用体变量时,一定要记住某一时刻只能有某一个成员起作用。只能引用共用体变量的成员,而不能引用整个共用体变量。引用形式为:
    共用体变量名.成员名
    un1.c1,un2.c2,un1.c3是合法的引用。
    可通过指向共用体的指针变量引用共用体变量,引用形式为:
    共用体指针变量-〉成员名 或 (*共用体指针变量).成员名
    语句“union un *pu;pu=&un1;”之后,(*pu).c,pu ->k是合法的引用。
    说明:
    给共用体变量赋值时,只能对共用体的一个成员赋值,而不能对整个共用体变量赋值。对共用体变量而言,只有最近一次被赋值的成员是有效的,其他成员无效
    展开全文
  • 结构体struct和联合体union最全讲解

    万次阅读 多人点赞 2018-05-30 15:32:17
    首先了解一下struct的储存结构:一、结构体的访问1.结构体成员的的直接访问,如下结构体:struct A{ int a; long *b; char c[20];};struct A com;结构体成员通过操作符"."访问,表达式com.a的结果是个...

    摘要:首先感谢三位博主,并做出总结.


    首先了解一下struct的储存结构:

    一、结构体的访问

    1.结构体成员的的直接访问,如下结构体:

    struct  A{

               int a;

               long *b;

               char c[20];

    };

    struct A   com;

    结构体成员通过操作符"."访问,表达式com.a的结果是个数组名,可以把它使用在任何可以使用数组名的地方,com.a[4],将选择一个数组元素。

    2、结构体成员的间接访问

    struct A *p;

    可以使用(*p).a访问结构体成员,但这种形式有点不简洁所以使用操作符"->"来访问结构体成员,箭头操作符对左操作数执行间接访问来获取指针所指向的结构,然后根据右操作数来访问一个成员,p->a。

    二、结构体的自引用

    struct B{

             int a;

             struct B b;

             int c;

    };

    这种引用是不合法的,因为b是一个完整的结构,第二个成员又是另一个完整的结构,还包括她自己的成员,这样会循环下去无法及所结构体的大小。

    struct B{

             int a;

             struct B  *b;

             int c;

    };

    这种声明是合法的,b现在是一个指针它所占的字节数是已知的,可以计算出结构体的大小,这种自引用是合法的。

    三、结构体、指针和成员

    typedef   struct{

        int a;

        short b[2];

    }Ex1;

    typedef   struct{

        int a;

        char b[3];

        Ex1 c;

        struct Ex1 d;

    }Ex2;

    Ex2 x={1,"My",{2,{3,4}},0};

    Ex2 *p=&x;

    如下图来表示此结构:

    创建一个指向整型的指针:int *p1;若要使它指向整型成员a,应使用&取得一个指向p->a的指针:p1=&p->a.

    访问嵌套的结构体:p->c.a即为访问c结构体中的整形a。

    访问指针成员:定义另一结构:Ex y;     x.d=&y;则Ex->d->c.b[1]=4;则表示如下图空间:

    四、结构体的内存对齐

    对齐规则

    每个特定平台上的编译器都有自己的默认“对齐系数”,也可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
    规则:
    1、数据成员对齐规则:struct数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。(即第一个数据成员以后的成员的偏移地址为#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个的整数倍)
    2、struct的整体对齐规则:在数据成员完成各自对齐之后,结构体本身也要进行对齐,对齐将按照#pragma pack指定的数值和struct最大数据成员长度中,比较小的那个进行。
    3、当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。
         当结构体里面包含另一结构体时,直接将该结构体中的内容代换进去,计算其总的存储空间即可。

    例:(在此平台上int占4个字节)

    虽然A和A1所包含的成员相同,但A占了12个字节,A1占8个字节,所以在声明中对结构体列表的排列,因该让边界要求严格的成员首先出现(数据成员自生长度大的先出现)

    以上转载自:https://www.cnblogs.com/Blog-day/p/MY_Blog_Days-3.html


    1.联合体union的基本特性——和struct的同与不同

    union,中文名“联合体、共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。

    不过区别也挺明显:

    结构体(struct)中所有变量是“共存”的——优点是“有容乃大”,全面;缺点是struct内存空间的分配是粗放的,不管用不用,全分配。

    而联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”;但优点是内存使用更为精细灵活,也节省了内存空间。

     

     

    2.双刃剑——多种访问内存途径共存

    一个例子了然:

     

    1. //example  
    2. #include<stdio.h>  
    3. union var{  
    4.         long int l;  
    5.         int i;  
    6. };  
    7. main(){  
    8.         union var v;  
    9.         v.l = 5;  
    10.         printf("v.l is %d\n",v.i);  
    11.         v.i = 6;  
    12.         printf("now v.l is %ld! the address is %p\n",v.l,&v.l);  
    13.         printf("now v.i is %d! the address is %p\n",v.i,&v.i);  
    14. }  
    15. 结果:  
    16. v.l is 5  
    17. now v.l is 6! the address is 0xbfad1e2c  
    18. now v.i is 6! the address is 0xbfad1e2c  

     

    所以说,管union的叫共用体还真是贴切——完全就是共用一个内存首地址,并且各种变量名都可以同时使用,操作也是共同生效。如此多的access内存手段,确实好用,不过这些“手段”之间却没法互相屏蔽——就好像数组+下标和指针+偏移一样。

    上例中我改了v.i的值,结果v.l也能读取,那么也许我还以为v.l是我想要的值呢,因为上边提到了union的内存首地址肯定是相同的,那么还有一种情况和上边类似:

    一个int数组变量a,一个long int(32位机中,long int占4字节,与int相同)变量b,我即使没给int变量b赋值,因为数据类型相同,我使用int变量b也完全会拿出int数组a中的a[0]来,一些时候一不小心用上,还以为用的就是变量b呢~

    这种逻辑上的错误是很难找出来的(只有当数据类型相去甚远的时候稍好,出个乱码什么的很容易发现错误)。

     

    PS:感谢热心网友的提醒“在union定义结束时加分号”,其实是可以不加的,因为他不在主函数内,不是执行的语句,如果是主函数内声明的union就必须加分号了,在主函数内不加分号就涉及到基础常识了——没有分号隔开怎能叫一句。

     

    3.联合体union和大小端(big-endian、little-endian):


    1. #include<stdio.h>  
    2. union var{  
    3.         char c[4];  
    4.         int i;  
    5. };  
    6.   
    7. int main(){  
    8.         union var data;  
    9.         data.c[0] = 0x04;//因为是char类型,数字不要太大,算算ascii的范围~  
    10.         data.c[1] = 0x03;//写成16进制为了方便直接打印内存中的值对比  
    11.         data.c[2] = 0x02;  
    12.         data.c[3] = 0x11;  
    13. //数组中下标低的,地址也低,按地址从低到高,内存内容依次为:04,03,02,11。总共四字节!  
    14. //而把四个字节作为一个整体(不分类型,直接打印十六进制),应该从内存高地址到低地址看,0x11020304,低位04放在低地址上。  
    15.         printf("%x\n",data.i);  
    16. }  


    结果:
    11020304
    证明我的32位linux是小端(little-endian)

     

     


    4.联合体union所占内存空间大小:

    前边说了,首先,union的首地址是固定的,那么,union到底总共有多大?根据一些小常识,做个不严谨不高深的基础版验证吧。

    根据:分配栈空间的时候内存地址基本上是连续的,至少同类型能保证在一起,连续就说明,我如果弄三个结构体出来,他们三个地址应该连着,看一下三个地址的间隔就知道了。

    1. #include<stdio.h>  
    2. union sizeTest{  
    3.         int a;  
    4.         double b;  
    5. };  
    6. main(){  
    7.         union sizeTest unionA;  
    8.         union sizeTest unionB;  
    9.         union sizeTest unionC;  
    10.   
    11.         printf("the initial address of unionA is %p\n",&unionA);  
    12.         printf("the initial address of unionB is %p\n",&unionB);  
    13.         printf("the initial address of unionC is %p\n",&unionC);  
    14. }  



    打印,可以看到结果:

    the initial address of unionA is 0xbf9b8df8
    the initial address of unionB is 0xbf9b8e00
    the initial address of unionC is 0xbf9b8e08

    很容易看出,8,0,8,这间隔是8字节,按double走的。

    怕不保险,再改一下,把int改成数组,其他不变:


    1. union sizeTest{  
    2.         int a[10];  
    3.         double b;  
    4. };  


    此时sizeTest大小为16字节,因为需要当数组为a[10] size大小为10,取较小值的最小公倍数.8*2 = 16. 


    5.联合体union适用场合:

    有了前边那个验证,基本可以确认,union的内存是照着里边占地儿最大的那个变量分的。

    也就可以大胆的推测一下,这种union的使用场合,是各数据类型各变量占用空间差不多并且对各变量同时使用要求不高的场合(单从内存使用上,我觉得没错)。

    像上边做的第二个测试,一个数组(或者更大的数组int a[100]),和一个或者几个小变量写在一个union里,实在没什么必要,节省的空间太有限了,还增加了一些风险(最少有前边提到的逻辑上的风险)。所以,从内存占用分析,这种情况不如直接struct。

     

    不过话说回来,某些情况下虽然不是很节约内存空间,但是union的复用性优势依然存在啊,比如方便多命名,这种“二义性”,从某些方面也可能是优势。这种方法还有个好处,就是某些寄存器或通道大小有限制的情况下,可以分多次搬运。

     

     

    6.本质&进阶:

     

    根据union固定首地址union按最大需求开辟一段内存空间两个特征,可以发现,所有表面的定义都是虚的,所谓联合体union,就是在内存给你划了一个足够用的空间,至于你怎么玩~它不管~!(何止是union和struct,C不就是玩地址么,所以使用C灵活,也容易犯错)

     

    没错,union的成员变量是相当于开辟了几个接口(即union包含的变量)!但是,没开辟就不能用了?当然也能用!

    写个小测试:

    1. #include<stdio.h>  
    2. union u{  
    3.         int i;  
    4.         double d;//这个union有8字节大小  
    5. };  
    6. main(){  
    7.         union u uu;  
    8.         uu.i = 10;  
    9.         printf("%d\n",uu.i);  
    10.   
    11.         char * c;  
    12.         c = (char *)&uu;//把union的首地址赋值、强转成char类型  
    13.         c[0] = 'a';  
    14.         c[1] = 'b';  
    15.         c[2] = 'c';  
    16.         c[3] = '\0';  
    17.         c[4] = 'd';  
    18.         c[5] = 'e';  
    19. //最多能到c[7]  
    20.         printf("%s\n",c);//利用结束符'\0'打印字符串"abc"  
    21.         printf("%c %c %c %c %c %c\n",c[0],c[1],c[2],c[3],c[4],c[5]);  
    22. }  

    一个例子了然,我的结构体只定义了int和double“接口”,只要我获得地址,往里边扔什么数据谁管得到?这就是C语言的强大,这就是union的本质——只管开辟一段空间。

    有些东西,熟悉编译原理和编译器工作过程的话,解决会更容易点,虽然我现在这方面技能不太强,不过一般问题也足够分析了。


    以上转自:https://www.cnblogs.com/tianlangshu/p/5204521.html.


    结构体的嵌套问题

    结构体的自引用(self reference),就是在结构体内部,包含指向自身类型结构体的指针。

    结构体的相互引用(mutual reference),就是说在多个结构体中,都包含指向其他结构体的指针。

    1. 自引用结构体

    1.1 不使用typedef时

    错误的方式:

    struct tag_1{
        struct tag_1 A;  
        int value;
    };

            这种声明是错误的,因为这种声明实际上是一个无限循环,成员A是一个结构体,A的内部还会有成员是结构体,依次下去,无线循环。在分配内存的时候,由于无限嵌套,也无法确定这个结构体的长度,所以这种方式是非法的。

    正确的方式: (使用指针

    struct tag_1{
        struct tag_1 *A; 
        int value;
    };

            由于指针的长度是确定的(在32位机器上指针长度为4),所以编译器能够确定该结构体的长度。

    1.2 使用typedef 时

    错误的方式:

    typedef struct {
        int value;
        NODE *link; 
    } NODE;

      这里的目的是使用typedef为结构体创建一个别名NODEP。但是这里是错误的,因为类型名的作用域是从语句的结尾开始,而在结构体内部是不能使用的,因为还没定义。

    正确的方式:有三种,差别不大,使用哪种都可以。

    复制代码
    typedef struct tag_1{
        int value;
        struct tag_1 *link; 
    } NODE;
    
    
    struct tag_2;
    typedef struct tag_2 NODE;
    struct tag_2{
        int value;
        NODE *link;   
    };
    
    
    struct tag_3{
        int value;
        struct tag_3 *link; 
    };
    typedef struct tag_3 NODE;
    复制代码

     

    2. 相互引用 结构体

    错误的方式:

    复制代码
    typedef struct tag_a{
        int value;
        B *bp; 
    } A;
    
    typedef struct tag_b{
        int value;
        A *ap;
    } B;
    复制代码

           错误的原因和上面一样,这里类型B在定义之前 就被使用。

    正确的方式:(使用“不完全声明”)

    复制代码
    struct tag_a{
        struct tag_b *bp; 
        int value;
    };
    struct tag_b{
        struct tag_a *ap;
        int value;
    };
    typedef struct tag_a A;
    typedef struct tag_b B;
    
    
    
    struct tag_a;  
    struct tag_b;
    typedef struct tag_a A;
    typedef struct tag_b B;
    struct tag_a{
        struct tag_b *bp; 
        int value;
    };
    struct tag_b{
        struct tag_a *ap;
        int value;
    };
    复制代码

     

    嵌套结构体时应注意:

    结构体的自引用中,如下这种情况是非法的
    struct s_ref {
     int a;
     struct s_ref b;
     char c;
    };
    因为结构体内部又包含自身结构体类型b,这个长度不能确定,只能向下再查找,又包含自身结构体类型b,又再向下查找,如此循环,类似于永无出口的递归调用,是非法的。

    但很多时候,的确需要使用到自引用,有个技巧,如下:
    struct s_ref {
     int a;
     struct s_ref *b;  //注意这句与上面相同位置的区别
     char c;
    };
    这是合法的,因为此处是定义了一个指向结构体的指针,指针的大小在具体的机器平台和编译器环境中都是已知的(即使不同的平台环境的定义不完全相同)。所以不会导致上述的递归死循环。是合法和可行的。但是要提醒的是:这个指针看似指向自身,其实不是,而是指向同一类型的不同结构。
    链表和树的数据结构就都使用到此技巧。自身的结构体指针指向下一节点或者下一子树的地址。

    这里有一种情况值得注意:
    typedef struct {   //这里是结构体类型定义
     int a;
     s_ref *b;  //注意这句引用了结构体类型名
     char c;
    }s_ref ;
    这个结构体类型定义是为了定义类型名s_ref,但却失败了。因为结构体中就引用了结构类型名,而此时还没定义类型名。
    可以改为如下:
    typedef struct s_ref_t{   //这里是结构体类型定义和结构体标签
     int a;
     struct s_ref_t *b;  //注意这句与上面相同位置的区别,使用了标签
     char c;
    }s_ref ;
    这里将运行良好。


    以上转自:http://www.cnblogs.com/renyuan/archive/2012/11/30/2796792.html.

    下面有个测试小程序:(基本上涵盖了所有的情况)帮助你更好的理解结构体和联合体占用的内存大小.

    #include <stdio.h>
    
    
    void main()
    {
    	typedef struct{
    		int a;
    		short b;
    	}struct_1;
    	typedef struct_1* struct_0;
    
    
    	typedef struct{
    		int a;
    		char b;
    		struct_1 s1;
    	}struct_2;
    
    	typedef struct{
    		int a;
    		char b;
    		long int c;
    		struct_1 s1;
    	}struct_3;
    
    	typedef struct{
    		int a;
    		char b;
    		struct_1 * s1;
    	}struct_4;
    	typedef struct{
    		struct_1 * s1;
    	}struct_5;
    	
    	typedef struct{
    		struct_0 s1;
    	}struct_6;
    	
    	union union_0{
    		int a;
    		char b[30];
    		long int c;
    	}union_1;
    	union test_a{
    		int a;
    		double b;
    	};
    	
    
    	
    	typedef struct{
    		int a;
    		short b;
    		union union_0 *c;
    	}struct_7;
    	
    	typedef struct{
    		int a;
    		struct struct_1* b;
    	}struct_8;
    
    	union test{
    		long int a;
    		char c[10];
    	};
    
    	typedef struct{
    		char b[7];
    	}struct_size7;
    	typedef struct{
    		char a[9];
    	}struct_size9;
    
    	union test_3{
    		struct_size7 c;
    		struct_size9 d;
    	};
    
    	typedef struct{
    		int a;
    		char b[10];
    	}struct_12;
    	union test_11{
    		int a;
    		char b[10];
    	};
    	union test_3 union_7add9;
    	union test test_1;	
    	union test_a test_2;
    	union test_11 test_12;
    	printf("struct_1 size = %d\n",sizeof(struct_1));
    	printf("struct_2 size = %d\n",sizeof(struct_2));
    	printf("struct_3 size = %d\n",sizeof(struct_3));
    	printf("struct_4 size = %d\n",sizeof(struct_4));
    	printf("struct_5 size = %d\n",sizeof(struct_5));
    	printf("struct_6 size = %d\n",sizeof(struct_6));
    	printf("union_1  size = %d\n",sizeof(union_1));
    	printf("struct_7 size = %d\n",sizeof(struct_7));
    	printf("struct_8 size = %d\n",sizeof(struct_8));
    	printf("test_1 size = %d\n",sizeof(test_1));
    	printf("test_2 size = %d\n",sizeof(test_2));
    	printf("struct_size7 = %d\n",sizeof(struct_size7));
    	printf("struct_size9 = %d\n",sizeof(struct_size9));
    	printf("union_7add9 = %d\n",sizeof(union_7add9));
    	printf("struct_12 = %d\n",sizeof(struct_12));
    	printf("test_12 = %d\n",sizeof(test_12));
    }
    

    输出结果:

    struct_1 size = 8
    struct_2 size = 16
    struct_3 size = 24
    struct_4 size = 16
    struct_5 size = 8
    struct_6 size = 8
    union_1  size = 32
    struct_7 size = 16
    struct_8 size = 16
    test_1 size = 16
    test_2 size = 8
    struct_size7 = 7
    struct_size9 = 9
    union_7add9 = 9
    struct_12 = 16
    test_12 = 12
    



    展开全文
  • 在实际问题,一组数据往往具有不同的数据类型。例如,在学生登记表,姓名...为了解决这个问题,C语言给出了另一种构造数据类型——“结构(structure)”或叫“结构体”。它相当于其它高级语言的记录。“结构

    在实际问题中,一组数据往往具有不同的数据类型。例如,在学生登记表中,姓名应为字符型;学号可为整型或字符型;年龄应为整型;性别应为字符型;成绩可为 整型或实型。显然不能用一个数组来存放这一组数据。因为数组中各元素的类型和长度都必须一致,以便于编译系统处理。为了解决这个问题,C语言中给出了另一 种构造数据类型——“结构(structure)”或叫“结构体”。 它相当于其它高级语言中的记录。“结构”是一种构造类型,它是由若干“成员”组成的。每一个成员可以是一个基本数据类型或者又是一个构造类型。结构既是一 种“构造”而成的数据类型,那么在说明和使用之前必须先定义它,也就是构造它。如同在说明和调用函数之前要先定义函数一样。
    让编程序的人自定义一个数据类型。 共用体是在同一存储空间上存不同类型的数据,用于节省空间 

     

     

    结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。

       在C语言中,可以定义结构体类型,将多个相关的变量包装成为一个整体使用。在结构体中的变量,可以是相同、部分相同,或完全不同的数据类型。在C语言 中,结构体不能包含函数。在面向对象的程序设计中,对象具有状态(属性)和行为,状态保存在成员变量中,行为通过成员方法(函数)来实现。C语言中的结构 体只能描述一个对象的状态,不能描述一个对象的行为。在C++中,考虑到C语言到C++语言过渡的连续性,对结构体进行了扩展,C++的结构体可以包含函 数,这样,C++的结构体也具有类的功能,与class不同的是,结构体包含的函数默认为public,而不是private。

      C++控制台输出例子:

      #include <cstdlib>

      #include <iostream>

      //定义结构体

      struct point

      {

      //包含两个变量成员

      int x;

      int y;

      };

      using namespace std;

      int main(int argc, char *argv[])

      {

      point pt;

      pt.x=1;

      pt.y=2;

      cout<<pt.x<<endl<<pt.y<<endl;

      return EXIT_SUCCESS;

      }


    、、、、、、、、、、、、、、、、、、、

    联合体(union)

    在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体。

    一般定义形式


      union 共用体名

      {

      成员表列

      }变量表列;

     

    简单示例


      union data

      {

      int i;

      char ch;

      float f;

      }a,b,c;

    [编辑本段]共用体变量的引用方式

      只有先定义了共用体变量才能在后续程序中引用它,有一点需要注意:不能引用共用体变量,而只能引用共用体变量中的成员。

     

    简单示例


      union data

      {

      int i;

      char ch;

      float f;

      }a,b,c;

      对于这里定义的共用体变量a,b,c。下面的引用方式是正确的:

      a.i (引用共用体变量中的整型变量i)

      a.ch (引用共用体变量中的字符变量ch)

      a.f (引用共用体变量中的实型变量f)

      而不能自引用共用体变量,例如:

      printf("%d",a); <==这种用法是错误的。

      因为a的存储区内有好几种类型的数据,分别占用不同长度的存储区,近些共用体变量名a,难以使系统确定究竟输出的是哪一个成员的值。

      而应该写成

      printf("%d",a.i); 或 printf("%c",a.ch);

    [编辑本段]共用体类型数据的特点

      1.同一个内存段可以用来存放几种不同类型的成员,但是在每一瞬间只能存放其中的一种,而不是同时存放几种。换句话说,每一瞬间只有一个成员起作用,其他的成员不起作用,即不是同时都在存在和起作用。

      2.共用体变量中起作用的成员是最后一次存放的成员,在存入一个新成员后,原有成员就失去作用。

      3.共用体变量的地址和它的各成员的地址都是同一地址。

      4.不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,并且,不能在定义共用体变量时对它进行初始化。

      5.不能把共用体变量作为函数参数,也不能是函数带回共用体变量,但可以使用指向共用体变量的指针。

      6.共用体类型可以出现在结构体类型的定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型的定义中,数组也可以作为共用体的成员。

    展开全文
  • C语言指向内容不确定的结构体怎么用指针实现比如有两个结构体typedefstructMsg1{inta;floatb;intc;}M1;typedefstructMsg2{chara[20];intb;}M2;一个函数执行完毕后可能返回Msg1或Msg2结构体,怎么让返回值用指针实现...
  • void*代表的是他所指向的就是一块内存,具体里面有多大是不知道的。int*和char*等指针之间是不可以互相转换的,但是任何指针都可以无屏障地转化到void*,他是一个万能指针。可以提供一种数据抽象能力。但void*会导致...
  • 结构体:用户自己建立不同数据类型组成的组合型的数据结构。 struct student { 成员列表 }; struct student student1; // struct为声明结构体类型的关键字,student为结构体名 // struct student 为一个...
  • 其实呢,c语言有很多核心的考点,今天小编就给大家介绍以下关于c语言当中的结构体和共用体,其中就包括结构体类型的说明、结构体变量的定义、结构体成员的引用、共用体以及链表。(一)结构体类型的说明1.定义:结构体...
  • 小议结构体中的大小

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

    2020-09-02 13:07:35
    struct 结构体名 {成员}变量;... 指向结构体数组:p=stu,p指向第一个元素,p+1指向第二个元素,(++p)->num即p先指向下一个元素(相当于数组名+1)再得到指向的成员值 void print(struct ...
  • 结构体中定义string变量

    千次阅读 2013-09-15 22:33:59
    我编写一个程序,在结构体中定义了一个string类型类型的变量:如下: typedef struct GS_DB_Event_Item_Stru {  string strFieldName;  uint16 usType; //1 // 1 number, 2 string  union  {  int32 nValue...
  • C结构体 C 数组允许定义可存储相同类型数据项的变量,结构是 C 编程另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。 定义结构 为了定义结构,我们必须使用struct语句。struct 语句定义了一...
  • C结构体学习

    千次阅读 多人点赞 2018-10-18 20:41:07
    C结构体学习初识结构体声明结构体类型定义结构体变量结构体的存储形式结构体的应用访问结构体成员初始化结构体变量结构体变量的赋值结构体数组定义结构体数组初始化结构体数组结构体数组示例结构体指针指向结构体...
  • 记得之前在哪里看到了如下形式的结构体和联合体的命名方式; union { char alpha; int num; }; struct { char alpha; int num; }; 因为写代码的时候用到了,在外网上找了点资料,把这个点记下来; Anonymous unions/...
  • 三、结构体指针(指向结构体的指针) 1.定义 2.获取结构体成员 3.结构体指针作为函数参数 四、枚举类型(enum) 五、共用体(union) 前面已经介绍了整型(int,long,….),浮点型(flaot,do...
  • 结构体——struct 什么是结构体结构体是一些值的集合,这些值称为成员变量。结构体的每个成员可以是不同类型的变量,可以是标量、数组、指针,甚至是其他结构体结构体声明 struct P { int age;...
  • 联合体union 位字段 1 一般的方法定义屏蔽吗 2 用位字段来定义屏蔽吗 自定义类型typedef 字节对齐 pragma pachx 按x个字节对齐1.结构体struct1.1 结构体的基本知识#include &lt;stdio.h&gt;struct ...
  • C++ 中结构体

    2014-03-19 19:47:07
    C/C++语言的解释 结构体定义  结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。 结构体作用  结构体和其他类型基础数据类型一样,例如int类型,char... 结构体在函数的作用
  • 1,结构体中的内存对齐  我们常常会发现,当我定义了一个结构体但是siziof之后却发现结果常常大于我原来定义的在结构体里面所有类型的和,然后我查询了许多的资料,终于发现了内存对齐问题。  许多计算机系统...
  • 假设CPU一次从内存读取四个字节的数据,而现在内存存在一个char型的数据和一个int型的数据,如果内存不对齐,当CPU第一次跨越四个字节寻址找到了一个char型的数据,而此时CPU的指向到了int型的中间区域,导致这...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,095
精华内容 9,638
关键字:

结构体中指向union