结构体_结构体指针 - CSDN
结构体 订阅
结构体是由一批数据组合而成的一种新的数据类型。组成结构型数据的每个数据称为结构型数据的“成员”。 [1] 展开全文
结构体是由一批数据组合而成的一种新的数据类型。组成结构型数据的每个数据称为结构型数据的“成员”。 [1]
信息
学    科
计算机 [1]
外文名
struct [1]
中文名
结构体
结构体结构体变量
结构体是C语言中一种重要的数据类型,该数据类型由一组称为成员(或称为域,或称为元素)的不同数据组成,其中每个成员可以具有不同的类型。结构体通常用来表示类型不同但是又相关的若干数据。 [2]  结构体类型不是由系统定义好的,而是需要程序设计者自己定义的。C语言提供了关键字struct来标识所定义的结构体类型。 [2]  关键字struct和结构体名组合成一种类型标识符,其地位如同通常的int、char等类型标识符,其用途就像 int 类型标识符标识整型变量一样可以用来定义结构体变量。定义变量以后,该变量就可以像定义的其他变量一样使用了;成员又称为成员变量,它是结构体所包含的若干个基本的结构类型,必须用“{}”括起来,并且要以分号结束,每个成员应表明具体的数据类型。 [2] 
收起全文
精华内容
参与话题
  • C语言结构体定义

    千次阅读 多人点赞 2018-08-29 16:52:36
    C语言结构体定义在我看来类似数据库的表 如: #include <stdio.h> #include <string.h>   struct st1 {  int id;  char name[30];  char sex;  int score; };     ...

    C语言结构体定义在我看来类似数据库的表

    如:

    #include <stdio.h>

    #include <string.h>

     

    struct st1

    {

      int id;

      char name[30];

      char sex;

      int score;

    };

     

     

    int main()

    {

        struct st1 s1;

        s1.id = 1;

        strcpy(s1.name,"张三");

        s1.sex = 'm';

        s1.score = 90;

        puts("学号\t姓名\t性别\t分数");

        printf("%d\t%s\t%c\t%d\n",s1.id,s1.name,s1.sex,s1.score);

        printf("%d\t%s\t%c\t%d\n",s1.id,s1.name,s1.sex,s1.score);

        printf("%d\t%s\t%c\t%d\n",s1.id,s1.name,s1.sex,s1.score);

        printf("%d\t%s\t%c\t%d\n",s1.id,s1.name,s1.sex,s1.score);

        printf("%d\t%s\t%c\t%d\n",s1.id,s1.name,s1.sex,s1.score);

        printf("%d\t%s\t%c\t%d\n",s1.id,s1.name,s1.sex,s1.score);

        return 0;

    }

     

    结果:

    学号    姓名    性别    分数

    1       张三    m       90

    1       张三    m       90

    1       张三    m       90

    1       张三    m       90

    1       张三    m       90

    1       张三    m       90

     

     

    例2:cat st3.c

    #include <stdio.h>

    #include <string.h>

     

     

    typedef struct st1

    {

      int n;

      char m[20];

    }a;     //这里a是整个结构体的缩写,如:typedef unsigned int UINT,这里UNIT既是前面unsigned int 的缩写,注意如果这里没有typedef,那么后面a是一个结构体变量,而不是结构体定义的缩写。

     

    void input (a* pa)

    {

    printf("please input your id and name:");

    pa -> n = 8; //这里是指针初始化赋值,另外可以用(*pa).n = 8来赋值,等价的关系

    strcpy(pa -> m , "apple"); //给一个指针字符串赋值

    scanf("%d,%s",&pa -> n,pa -> m);

    }

     

    void print (a s)

    {

     puts("id\tname");

     printf("%d\t%s\n",s.n,s.m);

    }

    int main ()

    {

     struct st1 s1; //定义结构体变量s1

     a s2;   //定义结构体变量s2 这里用到了上面的缩写a代替struct st1

    // printf("Please input your id and name:");

    // scanf("%d,%s",&s1.n,s1.m);

     s2.n = 10; //结构体变量赋值

     s1.n = 11;//结构体变量赋值

     input(&s1);//调用输入函数

     print(s1);//输出你输入的内容

     return 0; 

    }

     

    cc st3.c -Wall

     ./a.out 

    please input your id and name:8,orange      //敲入8,orange 下面是输出的结果  

    id      name

    8       orange

    展开全文
  • c语言基础语法六——结构体(完结)

    万次阅读 多人点赞 2016-12-24 14:47:19
    关于c语言结构体的引入; 在前面已经介绍了整形(int,long,….),浮点型(flaot,double),字符型(char),还介绍了数组(存储一组具有相同类型的数据),字符串。但是在实际问题中只有这些数据类型是不够的,...

    1;关于c语言结构体的引入;
    在前面已经介绍了整形(int,long,….),浮点型(flaot,double),字符型(char),还介绍了数组(存储一组具有相同类型的数据),字符串。但是在实际问题中只有这些数据类型是不够的,有时候我们需要其中的几种一起来修饰某个变量,例如一个学生的信息就需要学号(字符串),姓名(字符串),年龄(整形)等等,这些数据类型都不同但是他们又是表示一个整体,要存在联系,那么我们就需要一个新的数据类型。
    ——结构体,他就将不同类型的数据存放在一起,作为一个整体进行处理。

    2;c语言使用结构体变量进一步加强了表示数据的能力。
    2.1;结构体声明;

    //申明一个结构体 
    struct book 
    {
        char title[MAXTITL];//一个字符串表示的titile 题目 ; 
        char author[MAXAUTL];//一个字符串表示的author作者 ; 
        float value;//一个浮点型表示的value价格; 
    };//注意分号不能少,这也相当于一条语句; 

    这个声明描述了一个由两个字符数组和一个float变量组成的结构体,但是注意,他并没有创建一个实际的数据对象,而是描述了一个组成这类对象的元素,【因此,我们也有时候将结构体声明叫做模板,因为它勾勒出数据该如何存储,并没有实例化数据对象】。
    下面介绍一下上面的结构体声明;
    1,首先使用关键字struct,他表示接下来是一个结构体。
    2;后面是一个可选的标志(book),它是用来引用该结构体的快速标记。因此我们以后就会可以这样创建数据对象

    struct book library;//把library设为一个可以使用book结构体的结构体变量,则library这个变量就包含了其book结构体中的所有元素

    3;接下来就是一个花括号,括起了结构体成员列表,及就是每个成员变量,使用的都是其自己的声明方式来描述,用分号来结束描述;
    列如;char title[MAXTITL];字符数组就是这样声明的,用分号结束;
    注意;其中每个成员可以使用任何一种c数据结构甚至是其他的结构体,也是可以的;

    4;在结束花括号后的分号表示结构体设计定义 的结束。

    2.2,关于其struct声明的位置,也就是这段代码要放到哪里。同样这也是具有作用域的。
    这种声明如果放在任何函数的外面,那么则可选标记可以在本文件中,该声明的后面的所有函数都可以使用。如果这种声明在某个函数的内部,则它的标记只能咋内部使用,并且在其声明之后;
    这里写图片描述
    这里写图片描述

    2.3;关于我们不断说的,标记名是可选的,那么我们什么时候可以省略,什么时候一定不能省略呢?
    如果是上面那种声明定义的方法,并且想在一个地方定义结构体设计,而在其他地方定义实际的结构体变量那么就必须使用标记;
    可以省略,设计的同时就创建该结构体变量,但是这种设计是一次性的,
    还有就是引入typedef。
    这个到后面的定义结构体变量一起说吧?

    关于结构体类型的定义的总结;
    一般格式就是;
    struct 结构体名(也就是可选标记名)
    {
        成员变量;
    };//使用分号表示定义结束;

    3;定义结构体变量;
    3.1;之前我们结构体类型的定义(结构体的声明)只是告诉编译器该如何表示数据,但是它没有让计算机为其分配空间。我们要使用结构体,那么就需要创建变量,也就是结构体变量;
    创建一个结构体变量;struct book library;
    看到这条指令,编译器才会创建一个结构体变量library,此时编译器才会按照book模板为该变量分配内存空间,并且这里存储空间都是以这个变量结合在一起的,这也是后面访问结构体变量成员的时候,我们就要用到结构体变量名来访问。
    分析;
    struct book的作用;在结构体声明中,struct book所起到的作用就像int,,,,等基础数据类型名作用一样。
    struct book s1,s2,*ss;
    定义两个struct book结构体类型的结构体变量,还定义了一个指向该结构体的指针,其ss指针可以指向s1,s2,或者任何其他的book结构体变量。
    其实;
    struct book library;
    等效于;
    struct book{
    char …
    ….
    …..
    }librar;
    这两种是等效的,只是第一种可以减少代码的编写量;
    3.2;现在还是回到刚才提及的那个问题,可选标志符什么时候可以省略;

    其一;
    struct
    {
        char title[MAXTITL]; 
        char author[MAXAUTL];
        float value; 
    }library;
    //注意这里不再是定义声明结构体类型,而是直接创建结构体变量了,这个编译器会分配内存的;
    //这样的确可以省略标识符也就是结构体名,但是只能使用一次;因为这是;声明结构体的过程和定义结构体变量的过程和在了一起;并且个成员变量没有初始化的;
    //如果你想多次使用一个结构体模块,这样子是行不通的;

    其二;

    typedef定义新类型名来代替已有类型名,即给已有类型重新命名;
    一般格式为;typedef 已有类型 新类型名;
    typedef int Elem; 
    typedef struct{
        int date;
        .....
        .....
    }STUDENT;
    STUDENT stu1,stu2;

    这里写图片描述

    总结一下关于结构体变量的定义;
    1;先定义结构体类型后再定义结构体变量;
    格式为;struct 结构体名 变量名列表;
    struct book s1,s2,*ss;//注意这种之前要先定义结构体类型后再定义变量;
    2;在定义结构体类型的同时定义结构体变量;
    格式为;
    struct 结构体名
    {
    成员列表;
    }变量名列表;//这里结构体名是可以省的,但尽量别省;
    struct book
    {
        char title[MAXTITL];//一个字符串表示的titile 题目 ; 
        char author[MAXAUTL];//一个字符串表示的author作者 ; 
        float value;//一个浮点型表示的value价格;
    }s1,s2;
    3,直接定义结构体类型变量,就是第二种中省略结构体名的情况;
    这种方式不能指明结构体类型名而是直接定义结构体变量,并且在值定义一次结构体变量时适用,无结构体名的结构体类型是无法重复使用的,也就是说,后面程序不能再定义此类型变量了,除非再写一次重复的struct落、

    4;对于结构体变量的初始化;
    4.1;先回忆一下关于基本数据类型和数组类型的初始化;
    int a = 0;
    int array[4] = {1,2,3,4};//每个元素用逗号隔开
    回忆一下数组初始化问题;
    这里写图片描述
    再回到结构体变量的初始化吧?
    关于结构体变量的初始化与初始化数组类似;
    也是使用花括号括起来,用逗号分隔的初始化好项目列表,注意每个初始化项目必须要和要初始化的结构体成员类型想匹配,

    struct book s1={//对结构体初始化 
            "yuwen",//title为字符串 
            "guojiajiaoyun",//author为字符数组 
            22.5    //value为flaot型 
        };
        //要对应起来,用逗号分隔开来,与数组初始化一样;

    4.2;加入一点小知识;
    关于结构体初始化和存储类时期的问题;
    如果要初始化一个具有静态存储时期的结构体,初始化项目列表中的值必须是常量表达式,
    如果存储时期是自动的,那么列表的值就不必是常量了;
    关于这点在讲存储类时期的时候在分析;
    4.3;注意如果在定义结构体变量的时候没有初始化,那么后面就不能全部一起初始化了;
    意思就是;

    /////////这样是可以的,在定义变量的时候就初始化了;
    struct book s1={//对结构体初始化 
            "guojiajiaoyun",//author为字符数组 
              "yuwen",//title为字符串 
              22.5
        };
    /////////这种就不行了,在定义变量之后,若再要对变量的成员赋值,那么只能单个赋值了;
    struct book s1;
        s1={ 
             "guojiajiaoyun",//author为字符数组 
              "yuwen",//title为字符串 
              22.5  
        };//这样就是不行的,只能在定义的时候初始化才能全部赋值,之后就不能再全体赋值了,只能单个赋值;
        只能;
        s1.title = "yuwen";........//单个赋值;
    

    4.4;对于结构体的指定初始化;
    《这个只存在于c99,》
    这里写图片描述

    5;访问结构体成员;
    5.1,结构体就像一个超级数组,在这个超级数组内,一个元素可以是char类型,下个元素就可以是flaot类型,再下个还可以是int数组型,这些都是存在的。在数组里面我们通过下标可以访问一个数组的各个元素,那么如何访问结构体中的各个成员呢?
    用结构成员运算符点(.)就可以了;
    结构体变量名.成员名;
    注意,点其结合性是自左至右的,它在所有的运算符中优先级是最高的;
    例如,s1.title指的就是s1的title部分,s1.author指的就是s1的author部分,s1.value指的就是s1的value部分。然后就可以像字符数组那样使用s1.title,象使用float数据类型一样使用s1.value;
    注意,s1;虽然是个结构体,但是s1.value却是float型的,因此s1.value就相当于float类型的变量名一样,按照float类型来使用;
    例如;printf(“%s\n%s\n%f”,s1.title,s1.author,s1.value);//访问结构体变量元素
    注意scanf(“%d”,&s1.value); 这语句存在两个运算符,&和结构成员运算符点,按照道理我们应该将(s1。value括起来,因为他们是整体,表示s1的value部分)但是我们不括起来也是一样的,因为点的优先级要高于&。
    5.2;如果其成员本身又是一种结构体类型,那么可以通过若干个成员运算符,一级一级的找到最低一级成员再对其进行操作;
    结构体变量名.成员.子成员………最低一级子成员;

    struct date
    {
        int year;
        int month;
        int day;
    };
    struct student
    {
        char name[10];
        struct date birthday;
    }student1;
    //若想引用student的出生年月日,可表示为;student.brithday.year;
    brithday是student的成员;year是brithday的成员;

    5.3;整体与分开
    5.3.1;可以将一个结构体变量作为一个整体赋值给另一相同类型的结构体变量,可以到达整体赋值的效果;这个成员变量的值都将全部整体赋值给另外一个变量;
    5.3.2;不能将一个结构体变量作为一个整体进行输入和输出;在输入输出结构体数据时,必须分别指明结构体变量的各成员;
    这里写图片描述

    总结;除开“相同类型的结构体变量可以相互整体赋值”外,其他情况下,不能整体引用,只能对各个成员分别引用;
    

    6;结构体数组,(这个在国二里面常考的类型,只要考结构体就离不开结构体数组和成员的访问,当然也只是简单的操作)
    6.1;为什么要引用结构体数组,显然,在上面的book类型的结构体 ,每本书就需要用一个book类型的结构体变量来描述,若是要描述两本书,需要使用两个这样的变量,依次类推;因此要使用一个该结构体的数组,来表示这些图书;并且数组就是存储一组具有相同类型的数据,因此就有了结构体数组的出现,注意本置,
    6.2;声明结构体数组
    与普通的数组声明一样,int a[10];int为元素的数据类型,a为数组名 【10】表示申请了10的int单元的内存;
    再看结构体声明;struct book library[10];是不是类似,struct book为数组元素的数据类型,library为数组名,[10]为申请了10个struct book单元的内存;
    解释;声明library为一个具体10个元素的数组,并且每个元素都book类型的结构,因此可以得到library[0],library[1]…….都是单独独立的一个book结构;
    注意library本身不是结构体名而是一个数组名;
    6.4;结构体数组的初始化;
    这里写图片描述
    两种初始化;就是在定义的时候赋值的两种情况;
    6.3;访问结构体数组的成员;
    规则;在结构体名后加点运算符,然后再是成员名;
    library[5].title;//表示第5个元素的title成员;library[5]是结构体变量名,title就是成员名;
    library[5].titlt[4];//注意title是数组类型,第5个数组元素的title成员的第4个字符;

    总结;
    library //book结构体的数组
    library[2]//数组的第二个元素,一个book结构体类型的变量名;
    library[2].title;//char数组,结构体数组的第二个元素的title成员;
    library[2].title[4];//表示一个字符,结构体数组的第二个元素的title成员的第四个字符;

    这里写图片描述

    7;指向结构体的指针,
    7.1;使用指向结构体的好处;就像指向数组的指针一样,它比数组本身更容易操作,指向结构体的指针通常也比结构体本身更容易操作;
    声明和初始化结构体指针,
    声明struct book * him;
    规则就是,struct 结构体名+ * + 指针名;
    这个声明不是建立一个新的结构体,而是创建了一个指针类型的him指针变量,他可以指向任何现有的book类型的结构体;
    him = &library[0];
    指针him正指向结构体library[0],如何使用him来取得library[0]的一个成员呢?
    方法一;
    引入一个运算符,->
    后跟->运算符的结构体指针和后跟.点运算符的结构体名是一样操作的;
    注意一点的是;不能使用him.成语;因为him不是结构体名;

    总结
    ->只用于结构体指针访问成员;
    .点只用于结构体名访问成员;

    方法二;
    如果him=&library[0],那么him=library[0];因为&和是一个互逆的运算符;
    &取地址,*取值;
    =》library[0].value 等价于 (*him).value;注意必须使用圆括号,优先级问题;
    然后都与him.value是一个作用;

    对于考国二懂得上面的也就差不多了;足够了;

    8;向函数传递结构体信息;
    8.1;传递结构体成员;
    只要结构体成员是具有单值的数据类型,(及int等基础数据类型)就可以把它作为参数传递给一个接受这个特定参数类型的函数;
    注意;这个只能实现访问,不能修改;
    8.2;使用结构体地址;
    这里写图片描述
    注意,如果不修改值,则设置为const;
    8.3;使用结构体作为参数传递;
    这里写图片描述
    其中s也是结构体变量,并且为s1结构体变量的副本。
    总结;
    结构体指针,使用->运算符访问成员;
    结构体名;使用.点运算符访问成员;
    要想通过调用函数修改实参结构体变量的值,只能传递地址,通过指针来修改;直在地址上修改;
    8.4;结构体之间的双向通信;
    先注意这个;c语言中对于结构体变量是可以整体赋值的,无论其成员是怎样的;

    传递地址,使用结构体指针接收,用于访问不做修改;const限制修改,

    这里写图片描述

    结构体作为参数传递;不能成功修改实参,只能访问;

    这里写图片描述

    结构体作为参数,修改结构体并且返回类型也为结构体;达到修改的目的;

    这里写图片描述

    传递地址,使用结构体指针接收,用于修改;不使用const限制修改,

    这里写图片描述

    通常我们是使用结构体指针的,如果不修改那么我们会使用const修改;

    9;在结构体中使用字符数组还是字符指针来存储字符串;
    答案先给出,尽量使用字符数组;
    9.1;使用字符数组;

    #define MAXTITL 100
    #define MAXAUTL 100
    struct book 
    {
        char title[MAXTITL];//一个字符串表示的titile 题目 ; 
        char author[MAXAUTL];//一个字符串表示的author作者 ; 
        float value;//一个浮点型表示的value价格; 
    }; 
    字符串的存储在结构体内部的;
    结构体总分配200个字节的内存给这两个字符串

    9.2;使用字符指针;

    struct book 
    {
        char *title; 
        char * author;  
    }; 
    这里的字符串是存储在编译器认为存储字符串常量的任何地方,这个结构体中存放的只有两个地址而已,值分配8分字节;结构体不为字符串分配任何内存存储空间,因此这时候在输入的时候存在了一个潜在的危险;
    scanf("%s",s.last);//把字符串放到由s.last指向的内存中因为这是一个未初始化的变量,因此该地址是可以指向任意大小的,因此此时就是一个潜在的危险;
    

    总结,因我们最好是使用字符数组来存储字符串;

    10;结构体和指针和malloc函数;
    这个可以看我之前的博客;
    http://blog.csdn.net/zw1996/article/details/53708591

    关于结构体的介绍就暂时到这里
    时间有点急,学得也不深,所以暂时先补充到这里,下次补上;
    还有未补充的内容;
    1;结构体数组的函数;
    2;结构体内容保存在文件当中;
    3;一些结构体的例子;

    展开全文
  • C语言结构体(struct)常见使用方法

    万次阅读 多人点赞 2019-11-13 00:27:27
    基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量。 (因为C++和C有共通之处,但是在...

    注意:盗版是不会得到修正和更新的!

     

    今天复习一下struct,顺便挖掘一下以前没注意的小细节:

    基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量。

    (因为C++和C有共通之处,但是在结构体上的某些机制又有所不同,所以后边提了一下,不喜欢可以略过)

     

    结构体定义:

     

    第一种:只有结构体定义

    struct stuff{
            char job[20];
            int age;
            float height;
    };

     

    第二种:附加该结构体类型的“结构体变量”的初始化的结构体定义

    //直接带变量名Huqinwei
    struct stuff{
            char job[20];
            int age;
            float height;
    }Huqinwei;

    也许初期看不习惯容易困惑,其实这就相当于:

    struct stuff{
            char job[20];
            int age;
            float height;
    };
    struct stuff Huqinwei;
    

     

    第三种:如果该结构体你只用一个变量Huqinwei,而不再需要用

    struct stuff yourname;

    去定义第二个变量。

    那么,附加变量初始化的结构体定义还可进一步简化出第三种

    把结构体名称去掉,用匿名结构体直接定义一个结构体对象(习惯用对象这词了),这样更简洁,不过也不能定义其他同结构体变量了——除非用typeof。

    struct{
            char job[20];
            int age;
            float height;
    }Huqinwei;

    使用typeof重新利用HU的结构体定义HU3,并且定义指针ptr1,ptr2

    #include <stdio.h>
    
    struct
    {
            char a;
            short b;
            int c;
    }HU;
    
    struct
    {
            char a;
            short b;
            int c;
    }HU2;
    
    int main(){
    
            printf("%ld\n",sizeof(HU));
    
            typeof(HU) HU3;
            printf("%ld\n",sizeof(HU3));
            printf("%ld\n",sizeof(HU2));
            typeof(HU) *ptr1 = &HU;
            typeof(HU) *ptr2 = &HU3;
            ptr2->b = 444;
            printf("%d\n",ptr2->b);
            ptr1 = ptr2;
            printf("%d\n",ptr1->b);
    
    
    }
    

    同样的写法,再定义一个结构体成员HU2,他们的“类型”不同,因为如果类型相同,肯定会报错了,实际并没有报。

    不过内存操作角度,HU2和HU应该没有任何区别,也可以用指针强行更改,前提是确认安全,比如没有不同文件不同平台对齐不兼容这种问题,所以C很万能,也很危险

     

    结构体变量及其内部成员变量的定义及访问:

    绕口吧?要分清结构体变量和结构体内部成员变量的概念。

     

    就像刚才的第二种提到的,结构体变量的声明可以用:

    struct stuff yourname;

    其成员变量的定义可以随声明进行:

       struct stuff Huqinwei = {"manager",30,185};
    

    也可以考虑结构体之间的赋值:

            struct stuff faker = Huqinwei;
    //或    struct stuff faker2;
    //      faker2 = faker;
    打印,可见结构体的每一个成员变量一模一样
    

    如果不使用上边两种方法,那么成员数组的操作会稍微麻烦(用for循环可能好点)

            Huqinwei.job[0] = 'M';
            Huqinwei.job[1] = 'a';
            Huqinwei.age = 27;
            Huqinwei.height = 185;
    

    结构体成员变量的访问除了可以借助符号".",还可以用"->"访问(下边会提)。

     

    引用(C++)、指针和数组:

    首先是引用和指针:

    int main()
    {
            struct stuff Huqinwei;
    
            struct stuff &ref = Huqinwei;
            ref.age = 100;
            printf("Huqinwei.age is %d\n",Huqinwei.age);
            printf("ref.age is %d\n",ref.age);
    
            struct stuff *ptr = &Huqinwei;
            ptr->age = 200;
            printf("Huqinwei.age is %d\n",Huqinwei.age);
            printf("ptr->age is %d\n",ptr->age);
    //既然都写了,把指针引用也加上吧
            struct stuff *&refToPtr = ptr;
            refToPtr->age = 300;
            printf("Huqinwei.age is %d\n",Huqinwei.age);
            printf("refToPtr->age is %d\n",refToPtr->age);
    
    
    }
    

     

    更正:之前给引用的初始化语句写错了,而且没注明引用是纯C中没有的东西(在这么个以C为幌子的博客中)。

    引用是C++特有的一个机制,必须靠编译器支撑,至于引用转换到C中本质是什么,我有个帖子写过
     

     

    结构体也不能免俗,必须有数组:

    struct test{
            int a[3];
            int b;
    };
    //对于数组和变量同时存在的情况,有如下定义方法:
            struct test student[3] =      {{{66,77,55},0},
                                            {{44,65,33},0},
                                            {{46,99,77},0}};
    //特别的,可以简化成:
            struct test student[3] =       {{66,77,55,0},
                                            {44,65,33,0},
                                            {46,99,77,0}};
    

     

    变长结构体

    可以变长的数组

    #include <stdio.h>
    #include <malloc.h>
    #include <string.h>
    typedef struct changeable{
            int iCnt;
            char pc[0];
    }schangeable;
    
    main(){
            printf("size of struct changeable : %d\n",sizeof(schangeable));
    
            schangeable *pchangeable = (schangeable *)malloc(sizeof(schangeable) + 10*sizeof(char));
            printf("size of pchangeable : %d\n",sizeof(pchangeable));
    
            schangeable *pchangeable2 = (schangeable *)malloc(sizeof(schangeable) + 20*sizeof(char));
            pchangeable2->iCnt = 20;
            printf("pchangeable2->iCnt : %d\n",pchangeable2->iCnt);
            strncpy(pchangeable2->pc,"hello world",11);
            printf("%s\n",pchangeable2->pc);
            printf("size of pchangeable2 : %d\n",sizeof(pchangeable2));
    }

    运行结果

    size of struct changeable : 4
    size of pchangeable : 4
    pchangeable2->iCnt : 20
    hello world
    size of pchangeable2 : 4

    如上,本例中变长结构体本身长度就是一个int的长度(这个int值通常只为了方便表示后边的数组长度),而后边的数组长度不计算在内,但是该数组可以直接使用。

    (说后边是个指针吧?指针也占长度!这个是不占的!原理很简单,这个东西完全是数组后边的尾巴,malloc开辟的是一片连续空间。其实这不应该算一个机制,感觉应该更像一个技巧吧

    20191113:这块可能有点抽象?建议去了解一下手动开辟空间malloc和指针相关知识,所谓“变长结构体”,不是一个你理解的结构体!至少不是按正常结构体用的,他像是一个逻辑性的概念,空间是malloc开辟的,结构体是以指针形式存在的“虚拟”的概念,简单说,这个“结构体”不在栈空间!

     

     

    20160405补充:

    非弹性数组不能用"char a[]"这种形式定义弹性(flexible)变量,必须明确大小。

    弹性数组在结构体中,下面的形式是唯一允许的:

     

    struct s
    {
            int a;
            char b[] ;
    };

    顺序颠倒会让b和a数据重合,会在编译时不通过。

    char b[] = "hell";也不行(C和C++都不行)

    少了整型变量a又会让整个结构体长度为0,compiler不允许编译通过!不同的是,其实C++形式上是允许空结构体的,本质上是通过机制避免了纯空结构体和类对象,自动给空结构体对象分配一个字节(sizeof()返回1)方便区分对象,避免地址重合!所以呢,C如果有空结构体,定义两个(或一打,或干脆一个数组)该结构体的变量(对象),地址是完全一样的!·!!!!!!!!调试看程序运行,这些语句其实都被当屁放了,根本没有运行,没有实际意义,C压根不支持空结构体这种东西(或者说我也没想好什么场合有用)

     

    struct s2
    {
    //      char a[]  = "hasd" ;
    //      int c;
    };
    int main()
    {
            struct s2 s22;
            struct s2 s23;
            struct s2 s24;
            struct s2 s25;
    }
    


    例外的是,C++唯独不给带弹性数组的结构体分配空间(可能怕和变长结构体机制产生某种冲突,比如大小怎么算):

    struct s
    {
            char b[] ;
    };

     

    struct s
    {
    //        char b[] ;
    };

    C++中两者是不一样的,空的结构体反而“大”(sizeof()返回1)
     

    20160321补充:这个机制利用了一个非常重要的特性——组和指针的区别!数组和指针在很多操作上是一样的,但是本质不一样。最直观的,指针可以改指向,数组不可以,因为数组占用的每一个内存地址都用来保存变量或者对象,而指针占用的内存地址保存的是一个地址,数组没有单独的保存指向地址的这样一个结构。数组的位置是固定的,正如指针变量自身的位置也是固定的,改的是指针的值,是指向的目标地址,而因为数组不存储目标地址,所以改不了指向。企图把地址强制赋值给数组的话,也只是说把指针赋值给数组,类型不兼容。

     

    结构体嵌套:

    结构体嵌套其实没有太意外的东西,只要遵循一定规律即可:

     

    //对于“一锤子买卖”,只对最终的结构体变量感兴趣,其中A、B也可删,不过最好带着
    struct A{ 
            struct B{
                 int c;
            }
            b;
    }
    a;
    //使用如下方式访问:
    a.b.c = 10; 
    

    特别的,可以一边定义结构体B,一边就使用上:

    struct A{
            struct B{
                    int c;
            }b;
    
            struct B sb;
    
    }a;
    

    使用方法与测试:

            a.b.c = 11;
            printf("%d\n",a.b.c);
            a.sb.c = 22;
            printf("%d\n",a.sb.c);
    结果无误。 

    但是如果嵌套的结构体B是在A内部才声明的,并且没定义一个对应的对象实体b,这个结构体B的大小还是不算进结构体A中。

     

     

    结构体与函数:

    关于传参,首先:

    void func(int);
    func(a.b.c);

    把结构体中的int成员变量当做和普通int变量一样的东西来使用,是不用脑子就想到的一种方法。

     

    另外两种就是传递副本和指针了 :

    //struct A定义同上
    //设立了两个函数,分别传递struct A结构体和其指针。
    void func1(struct A a){
            printf("%d\n",a.b.c);
    }
    void func2(struct A* a){
            printf("%d\n",a->b.c);
    }
    main(){
            a.b.c = 112;
            struct A * pa;
            pa = &a;
            func1(a);
            func2(&a);
            func2(pa);
    }
    
    

     

    注意:盗版是得不到更新迭代的(手动滑稽)https://blog.csdn.net/huqinweI987/article/details/23625823

     

     

    占用内存空间:

    struct结构体,在结构体定义的时候不能申请内存空间,不过如果是结构体变量,声明的时候就可以分配——两者关系就像C++的类与对象,对象才分配内存(不过严格讲,作为代码段,结构体定义部分“.text”真的就不占空间了么?当然,这是另外一个范畴的话题)。

     

    结构体的大小通常(只是通常)是结构体所含变量大小的总和,下面打印输出上述结构体的size:

            printf("size of struct man:%d\n",sizeof(struct man));
            printf("size:%d\n",sizeof(Huqinwei));
    结果毫无悬念,都是28:分别是char数组20,int变量4,浮点变量4. 

     

    下边说说不通常的情况:

    对于结构体中比较小的成员,可能会被强行对齐,造成空间的空置,这和读取内存的机制有关,为了效率。通常32位机按4字节对齐,小于的都当4字节,有连续小于4字节的,可以不着急对齐,等到凑够了整,加上下一个元素超出一个对齐位置,才开始调整,比如3+2或者1+4,后者都需要另起(下边的结构体大小是8bytes),相关例子就多了,不赘述。

    struct s
    {
    char a;
    short b;
    int c;
    }

    相应的,64位机按8字节对齐。不过对齐不是绝对的,用#pragma pack()可以修改对齐,如果改成1,结构体大小就是实实在在的成员变量大小的总和了。
    补一个代码,压入1字节对齐,定义s,然后弹出,使用默认,定义s2,两个结构体大小分别为7和8

    #include <stdio.h>
    #pragma pack(push,1)
    struct s
    {
            char a;
            short b;
            int c;
    };
    #pragma pack(pop)
    struct s2
    {
            char a;
            short b;
            int c;
    };
    
    
    
    int main(){
    
            printf("%ld\n",sizeof(struct s));
            printf("%ld\n",sizeof(struct s2));
    
    }
    
    $ ./a.out
    7
    8
    

     

    和C++的类不一样,结构体不可以给结构体内部变量初始化,。

    如下,为错误示范:

     

    #include<stdio.h>
    //直接带变量名Huqinwei
    struct stuff{
    //      char job[20] = "Programmer";
    //      char job[];
    //      int age = 27;
    //      float height = 185;
    }Huqinwei;
    

     

    PS:结构体的声明也要注意位置的,作用域不一样。

    C++的结构体变量的声明定义和C有略微不同,说白了就是更“面向对象”风格化,要求更低。

     

    那么熟悉了常用方法,都要注意哪些常犯错误呢,见C语言结构体常见错误

     

     

     

    展开全文
  • 结构体定义的几种常见方式

    万次阅读 多人点赞 2017-01-25 19:13:51
    大家都知道若struct后面接的是名字,则其为该结构体的名称。下面给出六种结构体定义,其中第一种是最基本的结构体定义,其定义了一个结构体A。struct A //第一种 { int a; };第二种则是在定义了一个结构体B的同时...

    大家都知道若struct后面接的是名字,则其为该结构体的名称。

    下面给出六种结构体定义,其中第一种是最基本的结构体定义,其定义了一个结构体A。

    struct A            //第一种
    {
        int a;
    };

    第二种则是在定义了一个结构体B的同时定义了一个结构体B的变量m。

    struct B            //第二种
    {
        int b;
    }m;

    第三种结构体定义没有给出该结构体的名称,但是定义了一个该结构体的变量n,也就是说,若是想要在别处定义该结构体的变量是不行的,只有变量n这种在定义结构体的同时定义变量才行。

    struct              //第三种
    {
        int c;
    }n;

    第四种结构体定义在第一种结构定义的基础上加了关键字typedef,此时我们将struct D{int d}看成是一个数据类型,但是因为并没有给出别名,直接用D定义变量是不行的。如D test;,不能直接这样定义变量test。但struct D test;可行。

    typedef struct D    //第四种
    {
        int d;
    };
    

    第五种结构体定义在第四种结构体定义的基础上加上了别名x,此时像在第四种结构体定义中说得那样,此时的结构体E有别名x,故可以用x定义E的结构体变量。用E不能直接定义,需要在前面加struct,如struct E test;。

    typedef struct E    //第五种
    {
        int e;
    }x;
    

    第六种结构体定义在第五种的基础上减去了结构体名,但是若是直接使用y来定义该结构体类型的变量也是可以的。如y test;。

    typedef struct      //第六种
    {
        int f;
    }y;

    因为也是学艺不精,若有出错或是某些地方考虑不周有遗漏还望指出,感激不尽。

    展开全文
  • 【C语言笔记】结构体

    千次阅读 多人点赞 2019-02-18 00:10:25
    本文更好的排版方式:【C语言笔记】结构体 我们都知道C语言中变量的类型决定了变量存储占用的空间。当我们要使用一个变量保存年龄时可以将其声明为int类型,当我们要使用一个变量保存某一科目的考试成绩时可以将其...
  • 结构体

    2019-12-10 19:33:30
    结构体变量的使用 赋值和初始化 定义的同时可以整体赋初值 定义完成后,只能单个的赋初值 如何去除结构体变量中的每一个成员 结构体变量名.成员名 指针变量名->成员名 指针变量名->成员名 在计算机内部会被...
  • 结构体的用法

    万次阅读 多人点赞 2018-07-08 23:45:26
    关于c语言结构体的引入; 在前面已经介绍了整形(int,long,….),浮点型(flaot,double),字符型(char),还介绍了数组(存储一组具有相同类型的数据),字符串。但是在实际问题中只有这些数据类型...
  • 什么是结构体?

    千次阅读 多人点赞 2018-05-08 20:22:11
    首先什么是结构体?其实结构体也是一种数据类型,只不过在这种数据类型中又包含了几个基本的数据类型;但为什么要有结构体这种数据类型呢?试想一下,假如我们要描述一个学生的基本信息,那一个学生有年龄,有性别,...
  • C语言中结构体变量的定义及引用

    万次阅读 多人点赞 2019-12-17 20:16:46
    一、结构体变量的定义 1.结构体类型与结构体变量分开定义 一般形式如下: struct<结构体名><结构体变量名>; eg:struct student student1,student2; 关键字struct要与结构体名student一起使用,...
  • 结构体是连续存储的,但由于结构体中成员类型各异,所以会存在内存对齐问题,也就是内存里面会有空档,具体的对齐方式这里 暂不讨论; 1.结构体的定义和赋值  结构体是可以直接初始化的,在定义的时候,...
  • 结构体定义的几种方式

    万次阅读 多人点赞 2017-10-07 10:41:26
    共计有三种形式,还有一种是typedef定义结构体
  • C语言-结构体指针及结构体嵌套

    万次阅读 2015-10-29 20:29:12
    C语言中结构体是一种构造类型,和数组、基本数据类型一样,可以定义指向该种类型的指针。结构体指针的定义类似其他基本数据类型的定义,格式如下 struct 结构体名 * 指针名; 比如: struct person{char[20] name...
  • sizeof全面总结——举一反三详细介绍sizeof(结构体)

    万次阅读 多人点赞 2020-08-08 23:17:27
    字节 short int float long *(地址) double long long 32位 2 4 ... ...
  • 结构体中嵌套结构体

    万次阅读 2016-08-12 22:11:00
    结构体的嵌套问题 结构体的自引用(self reference),就是在结构体内部,包含指向自身类型结构体的指针。 结构体的相互引用(mutual reference),就是说在多个结构体中,都包含指向其他结构体的指针。 1. ...
  • 假设有结构体 addr; memset(&addr,0,sizeof(addr)); memset()方法是在某个内存块内填充某一特定的值
  • C++结构体定义构造函数

    千次阅读 2018-07-09 09:40:45
    定义结构体可以使用构造函数:struct My{ int first; char c; My(){ first = 10; c = 'T'; } };不适用于c语言结构体
  • 1.struct结构体名 { //成员表列 }; 2.struct { //成员表列 }变量名; 结构体变量要和结构体同时定义。 3.struct结构体名 { //成员表列 }变量名; 结构体变量与结构体同时定义。 4.typedef struct 结构体...
  • 结构体成员的访问(->和 . )

    万次阅读 2016-06-14 17:36:08
    结构体成员的访问(->和 . )
  • C++中结构体的4种定义

    万次阅读 2018-12-28 16:03:48
    1. 先定义结构体类型再单独进行变量定义 struct Student { int Code; char Name[20]; char Sex; int Age; }; struct Student Stu; struct Student Stu[10]; struct Student *pStru; 结构体类型是struct ...
  • typedef关键字与结构体结构体指针的定义

    万次阅读 多人点赞 2015-08-17 11:21:13
    一使用typedef定义结构体 二使用typedef定义结构体指针 一、使用typedef定义结构体typedef用来定义新的数据类型,通常typedef与结构体的定义配合使用。使用typedef的目的使结构体的表达更加简练(所以说typedef语句...
1 2 3 4 5 ... 20
收藏数 476,069
精华内容 190,427
关键字:

结构体