精华内容
下载资源
问答
  • 结构体中的结构体指针是使用一、问题背景二、代码三、说明 一、问题背景   日常工作中没有编程的机会,所以只看得懂代码,现在需要重新写一段代码,实现固定格式存储数据,需要使用到结构体和结构体指针。数据...

    结构体中的结构体指针是使用



    一、问题背景

      日常工作中没有编程的机会,所以只看得懂代码,现在需要重新写一段代码,实现固定格式存储数据,需要使用到结构体和结构体指针。数据个数是非固定的,编写过程中用结构体指针会更方便,在使用结构体中的结构体指针时出现了很多问题。
      下面直接上代码,避免以后编程中使用结构体指针出现错误。


    二、代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>    
    
    #define OFFSET_NUM 3 //结构体指针偏移次数
    
    typedef struct
    {
        char str_a[20];
        double lf;
    }A;//声名一个结构体类型A
    
    typedef struct 
    {
        char str_b[20];
        A *pa;
    }B;//声名一个结构体类型B,其中包含一个A类型的结构体指针
    
    void print_A(A *a)//用来打印结构体中的数据
    {
        printf("a->str_a=%s\n",a->str_a);
        printf("a->lf=%2.3f\n",a->lf);
    }
    
    int main(int argc, char *argv[])  
    {   
        B *pb=(B *)malloc(sizeof(B));//先申请结构体指针的内存空间大小,此时编译器不会分配结构体内结构体指针的地址。
        pb->pa=(A *)malloc(sizeof(A)*OFFSET_NUM);//再申请结构体中的结构体指针内存空间大小,顺序反了将提示无法识别pb;内存空间一定要等于乘以需要使用的数量,否则数据可能会出错。
    
        int i;
        for(i=0;i<OFFSET_NUM ;i++)
        {
            strcpy(pb->pa->str_a,"string_A");//赋值
    	    pb->pa->lf=50.2+i;//赋值
            print_A(pb->pa);//将结构体指针pa地址作为参数输出打印信息
    	    pb->pa++;//移动到下一个大小为A的内存空间,相当于定义了一个结构体数组a[3](但是并不是)
        }
        pb->pa-=OFFSET_NUM ;//恢复指针指向的地址位置,否则free()释放空间时会报错,错误提示为:
                            //munmap_chunk(): invalid pointer: //原因是释放的没有申请过的内存
    
        free(pb->pa);//先释放结构体内部的结构体指针
        free(pb);//再释放结构体指针
        return 0;  
    }
    

    三、说明

      以上的注释并不代表说法完全正确,只是我一点点编程测试个人摸索的结果,所以如果有说的不合理的或者错误的地方,希望看到的人指出来。
      一直都没找到能将这类用法的书,如果有大佬看到了,希望留个书名我学习学习~~~


    展开全文
  • c语言结构体学习整理(结构体初始化,结构体指针)

    万次阅读 多人点赞 2018-11-01 20:22:12
    c语言中交换两个结构体的值(结构体指针) 1关于语言的结构体: 首先我们为什么要用到结构体,我们都已经学了很多int char …等类型还学到了同类型元素构成的数组,以及取上述类型的指针,在一些小应用可以灵活...

    渣渣c的c语言学习之路

    1.关于c语言的结构体:

    首先我们为什么要用到结构体,我们都已经学了很多int char …等类型还学到了同类型元素构成的数组,以及取上述类型的指针,在一些小应用可以灵活使用,然而,在我们实际应用中,每一种变量进行一次声明,再结合起来显然是不太实际的,类如一位学生的信息管理,他可能有,姓名(char),学号(int)成绩(float)等多种数据。如果把这些数据分别单独定义,就会特别松散、复杂,难以规划,因此我们需要把一些相关的变量组合起来,以一个整体形式对对象进行描述,这就是结构体的好处。

    2首先我们要了解一些小知识

    2.1**只有结构体变量才分配地址,而结构体的定义是不分配空间的。**
    2.2结构体中各成员的定义和之前的变量定义一样,但在定义时也不分配空间。
    2.3结构体变量的声明需要在主函数之上或者主函数中声明,如果在主函数之下则会报错
    2.4c语言中的结构体不能直接进行强制转换,只有结构体指针才能进行强制转换
    2.5相同类型的成员是可以定义在同一类型下的
    列如

    
    struct Student
    { 
    	int number,age;//int型学号和年龄
    	char name[20],sex;//char类型姓名和性别
    	float score;
    }

    最后的分号不要忘了 有的编译器会自动加上,因此有的同学就会不注意。

    3关于结构体变量的定义和引用

    在编译时,结构体的定义并不分配存储空间,对结构体变量才按其数据结构分配相应的存储空间

    
     struct Book
     { 
     	char title[20];//一个字符串表
    
    示的titile 题目
    	char author[20];//一个字符串表示的author作者
     	float value;//价格表示 
     };//这里只是声明 结构体的定义 
    struct Book book1,book2;//结构体变量的定义 分配空间
    
    book1.value;//引用结构体变量
    

    定义结构体变量以后,系统就会为其分配内存单元,比如book1和book2在内存中占44个字节(20+20+4)具体的长度你可以在你的编译器中使用sizeof关键字分别求出来。
    列如

    当然,要注意一点:用sizeof关键字求结构体长度时,返回的最大基本类型所占字节的整数倍 比方说我们上面求得的为44 为 float(4个字节)的整数倍,
    但是我们把title修改为title[22]; 这时正常长度为46 ,但是你会发现实际求得的为48,(4的整数倍)

    这就涉及到结构体的存储

    1结构体整体空间是占用空间最大的成员(的类型)所占字节数的整数倍。

    2.结构体的每个成员相对结构体首地址的偏移量(offset)都是最大基本类型成员字节大小的整数倍,如果不是编译器会自动补齐,

    关于这个我们简单介绍下:

    1.偏移量----偏移量指的是结构体变量中成员的地址和结构体变量首地址的差。即偏移字节数,结构体大小等于最后一个成员的偏移量加上他的大小,第一个成员的偏移量为0,

    struct S1
    {
        char a;
    
        int b;
    
        double c;
    };
    

    这里char a 偏移量为1 之后为int b 因为偏移量1不为int(4)的整数倍,所以会自动补齐,而在 double c 时,偏移量为8 是double(8)的整数倍,所以不用自动补齐 最后求得结构体得大小为 16

    具体看下图:
    在这里插入图片描述
    通过上面的代码同学们应该会有一个简单的认知

    4结构体变量的初始化

    结构体的初始化有很多需要注意的地方,这里我们说明下
    首先是几种初始化的方法
    ps在对结构体变量初始化时,要对结构体成员一一赋值,不能跳过前面成员变量,而直接给后面成员赋初值,但是可以只赋值前面几个,对与后面未赋值的变量,如果是数值型,则会自动赋值为0,对于字符型,会自动赋初值为NULL,即‘\0’

    4.1定义时直接赋值

    struct Student
    { 
    	char name[20];
    	char sex;
    	int number;
    }stu1={"zhaozixuan",'M',12345};
    //或者
    struct Student
    { 
    	char name[20];
    	char sex;
    	int number;
    }struct Student stu1={"zhaozixuan",'M',12345};
    
    

    注意字符为‘ ’ 字符串为""
    4.2定义结构体之后逐个赋值

    stu1.name="王伟";
    stu1.sex='M';
    stu1.number=12305;
    //也可用strcpy函数进行赋值
    strcpy(stu1.name,"王伟");
    
    

    4.3定义之后任意赋值

     struct Student stu1={
      .name="Wang",
      .number=12345,
      .sex='W', 
     };//可以对任意变量赋值
    

    这样写的好处时不用按照顺序来进行初始化,而且可以对你想要赋值的变量直接进行赋值,而不想赋值的变量可以不用赋值

    需要注意的是如果在定义结构体变量的时候没有初始化,那么后面就不能全部一起初始化了;

    等下结构体数组初始化时我们还会有一个讲解

    这里我们顺带提一下typedef说明结构体类型


    这里的BOOK就相当于struct book的一个别名一样,用它来定义结构体变量非常简便
    主要也是考二级要用到,所以我们简单介绍下

    5结构体变量的引用(输出和输入)

    5.1结构体变量的赋值用scanf赋值和printf输出时跟其他变量操作一样
    但是有几点需要注意
    (1) .是运算符,在所有运算符优先级中最高
    (2)如果结构体的成员本身是一个结构体,则需要继续用.运算符,直到最低一级的成员。

    struct Student
    {	char name[20];
    	char sex;
    	int number;
    	struct Date
    	{
    		int year;
     		int month;
     		int day;
    	}birthday;
    
    }stu1;
    printf("%d",stu1.birthday);//这样子是错误的,因为birthday也是一个结构体变量
    scanf("%d",&stu1.birthday.month);//正确
    

    (3)可以引用接头体变量成员的地址,也可以引用结构体变量的地址:

    printf("%o", student);(输出student的首地址)(%o 按八进制输出)

    6结构体数组及其初始化(重点)

    这里我们简单说下,具有相同类型的结构体变量组成数组就是结构体数组

    结构体数组与结构体变量区别只是将结构体变量替换为数组

    struct Student
    { 
    	char name[20];
    	char sex;
    	int number;
    }stu1[5]={
    	 {"zhaozixuan",'M',12345},
    	 {"houxiaohong",'M',12306},
    	 {"qxiaoxin",'W',12546},
    	 {"wangwei",'M',14679},
    	 {"yulongjiao",'W',17857}
    };
    stu1[3].name[3]//表示stu1的第三个结构变量中姓名的第五个字符
    //若初始化时已经是结构体数组全部元素[]中的数可以不写如stu1[]=
    

    注意结构体数组要在定义时就直接初始化,如果先定义再赋初值是错误的
    比如:

    struct Student stu1;
    stu1[3]={
      {"zhaozixuan",'M',12345},
      {"houxiaohong",'M',12306},
      {"qxiaoxin",'W',12546}
      };
      
    

    这样子是错误的,

    这里我在写的时候遇到一些问题,还是结构体数组初始化的问题,折腾了下解决了,给大家分享下
    对于数组初始化时
    比如

    char str[20];
    str="I love you";/* 这样会修改数组的地址,但是数组的地址分配之后是不允许改变的 */
    
    

    在第一条语句中 str就已经被定义成数组而在C99标准中不允许将字符串(实际上是一个指针变量) 赋值给数组,所以如果我们直接赋值是错误的

    那么怎么弄呢
    这里提供3种方法

    1.定义数组时直接定义
    char str[20]=“I love you”;

    2.用strcpy或者memset函数进行复制
    char str[20];
    strcpy(str,“I love you”);
    再用到memset函数时,出现了一些问题
    对于memcset函数简单介绍下

    memset
    void *memset(void *s,int c,size_t n)
    作用:将已开辟内存空间s的首n个字节的值设为值c。

    char str[20];
    memset(str,'a',20);
    

    如果是字符类型数组的话,memset可以随便用,但是对于其他类型的数组,一般只用来清0或者填-1,如果是填充其他数据就会出错

    int str[10];
    memset(str,1,sizeof(str));//这样是错误的
    
    

    这里我们说下这个错误,

    首先我们要知道memset在进行赋值时,是按字节为单位来进行赋值的,每次填充的数据长度为一个字节,而对于其他类型的变量,比如int,占4个字节 所以sizeof(str)=40; 而用memset赋值时,将会对指向str地址的前40个字节进行赋值0x01(00000001) 的操作,把0x00000000赋值4次0x01操作变为0x01010101(00000001000000010000000100000001)

    相当于给“前10个int”进行了赋值0x01010101的操作 对应十进制的16843009
    所以会出很大的错误

    这里请务必要注意,但是如果是清零一个数组用memset还是很方便的
    简单使用的话同学们用strcmp函数就行

    3用指针(注意内存分配)
    char *str;
    str=“I love you”;

    这两句话的本质是,在内存中开辟一段内存空间,把"I love you"放进这段内存空间,然后把这段内存空间的地址交给str,由于str是变量,所以给它赋值是合法的。

    请注意,在我们进行数组初始化的时候如果定义的数组过长,而我们只初始化了一部分数据,对于未初始化的数据如果是数值型,则会自动赋值为0,对于字符型,会自动赋初值为NULL,即‘\0’ 即不足的元素补以默认值
    这里我们在4小节中也提到了
    比如

    int str[10]={1};//这里只是把str的第一个元素赋值为1,其他元素默认为0
    
    



    7结构体与指针

    我们知道,指针指向的是变量所占内存的首地址,在结构体中,指针指向的是结构体变量的起始地址,当然也可指向结构体变量的元素
    这里我们分为三部分
    7.1指向结构体变量的指针

    定义形式一般为
    struct 结构体名* 指针名;
    比如: struct Student* p;

    struct Student
    {	
    	char cName[20];
     	int number;
     	char csex;  
    }student1;
    struct Student*p;
    p=&student1;
    //若为结构体数组则
    struct Student stu1[5];
    struct Student*p;
    p=stu1;//因为stu1为结构体数组而p=stu1直接是指向stu1的首地址,就不用再加&符
    
    

    用结构体指针变量访问结构体变量成员有以下两种方式:
    (*p).cName //这里的括号不能少,在5.1中有提到
    p->cName

    简单来说以下三种形式是等价的

    p->cName
    (*p).cName 
    student1.cName
    p->cName //可以进行正常的运算
    

    p->number++; 是将结构体变量中number的值进行运算,然后再加一,
    这里要注意下,等下在7.2中会有比较

    7.2指向结构体数组的指针

    7.1中我们已经提到结构体数组指针的命名,这里我们仅对一些知识点做下介绍
    这里我们接着来说结构体数组指针
    在我们想要用指针访问结构体数组的第n个数据时可以用

    struct Student stu1[5];
    struct Student*p;
    p=stu[n];
    (++p).number//是指向了结构体数组下一个元素的地址
    
    

    7.3结构体成员是指针类型变量
    比如

    struct Student
    {
     	char* Name;//这样防止名字长短不一造成空间的浪费
     	int number;
     	char csex;  
    }student1;
    
    

    在使用时可以很好地防止内存被浪费,但是注意在引用时一定要给指针变量分配地址,如果你不分配地址,结果可能是对的,但是Name会被分配到任意的一的地址,结构体不为字符串分配任何内存存储空间具有不确定性,这样就存在潜在的危险,

    struct Student
    {
     	char* Name;
     	int number;
     	char csex;  
    }stu,*stu;
    
    stu.name=(char*)malloc(sizeof(char));//内存初始化
    

    这里我们说一下,同学们看书的时候一般不会看到,
    如果我们定义了结构体指针变量,他没有指向一个结构体,那么这个结构体指针也是要分配内存初始化的,他所对应的指针类型结构体成员也要相应初始化分配内存

    struct Student
    {
     	char* Name;
     	int number;
    	char csex;  
    }stu,*stu;
    stu = (struct student*)malloc(sizeof(struct student));./*结构体指针初始化*/
      stu->name = (char*)malloc(sizeof(char));/*结构体指针的成员指针同样需要初始化*/  
    
    

    7.4二叉树遍历算法
    二叉树的二叉链表类型定义如下:
    typedef struct btnode {
    datatype data;
    struct btnode *lchild,*rchild;
    };
    这里我们仅仅提出以下,因为涉及到链表,感兴趣的同学可以去学习下(二级要用),
    7.5结构体作为函数参数

    首先我们要注意的一点,使用结构体变量作为函数参数的时候,采取的是值传递的方式,将结构体所占内存单元的内容全部传递给形参,并且形参必须也要是同类型的结构体变量,在使用时,会自动创建一个结构体变量作为原变量的副本,并且也需要占内存,并且在调用期间如果修改(形参)结构体中成员的值,修改值是无效的

    而如果用指针作为实参,传递给函数的形参,这时候传递的是结构体的地址,形参所指向的地址就是结构体变量的地址,这时候进行修改的话是可以修改的,这正是指针的精华所在

    在这里我们再提供几种互换两个结构体的方法

    struct Student
    {
     char cName[20];
     int number;
     char csex;  
    }student1,student2;
    struct Student student1={"Wang",12345,'W'};
    struct Student student2={"Zhao",54321,'M'}; 
    struct Student*stu1=&student1;
    struct Student*stu2=&student2;
    
    struct Student *student3;
    student3=stu1;
    stu1=stu2;
    stu2=student3;//互换地址
    
    2对于同类型结构体直接互换值就行
    struct stu student3;
    student3=student1;
    student1=student2;
    student2=student3;
    //这里也可以写成应strcmp函数互换
    
    3memcpy()函数进行互换
    
    
    4比较笨的方法: 用for循环互换
    

    最后提下memset清空结构体

    struct Student
    {
     char cName[20];
     int number;
     char csex;  
    }stu1;
    
    一般情况下,清空str的方法:
      str.cName[0]='\0';
      str.csex='0';
      str.number=0;
      但是我们用memset就非常方便:
      memset(&str,0,sizeof(struct Student));
      如果是数组:
      struct Student stu[10];
      就是
      memset(stu,0,sizeof(struct Student)*10);
    

    整理不易,点个赞再走呗!

    展开全文
  • 程序中有一个结构体指针,我想拷贝一份,建立一个新的结构体指针变量,并且分配内存。 可是结构体里面嵌套了多层结构体指针,这样分配内存好麻烦,一层一层的,也怕漏掉。 有没有什么好的办法进行这种结构体指针的...
  • 最近在STM的GPIO结构体定义中看到源代码的时候,顺便复习下结构体指针变量的定义及typedef 的使用。 1.结构体类型定义 定义方式1: Typedef struct LNode { int data; // 数据域 struct LNode *next; // 指针域 } *...

    最近在STM的GPIO结构体定义中看到源代码的时候,顺便复习下结构体指针变量的定义及typedef 的使用。
    1.结构体类型定义
    定义方式1:

    Typedef struct LNode {
    int data; // 数据域
    struct LNode *next; // 指针域
    } *LinkList;
    定义方式2:

    struct LNode {
    int data; // 数据域
    struct LNode *next; // 指针域

    };
    Typedef struct LNode *LinkList;
    以上两个定义方式是等价的,是将 *LinkList 定 义为 struct LNode 类型,即 LinkList 被定义为一个类型名。这样就可以用 LinkList来定义说明新的变量了,如:

    LinkList L;

    结构体变量与结构体指针变量的使用方法
    一、结构体的定义格式一般如下:

    Typedef struct SCI

    {

    U8 data[MAXLEN];
    
     U16 pos;
    

    }TSCI;

    二、访问结构体成员的基本方法有两种:

    1、定义一个结构体变量直接访问成员变量;

    2、定义一个结构体指针变量间接访问结构体变量。

    (1) 结构体变量访问

    TSCI Sci1;

    Sci1.data [ Sci1.pos++]= num;

    (2) 结构体指针变量访问

    TSCI *Sci2,b;

    Sci2= &b; //指针变量必须初始化 指向一个结构体变量

    Sci2->data[Sci2->pos++] = num;

    (3)(*Sci1).data Sci2->data 效果等效

    三、如何实现结构体被其他函数调用

    假设A文件中定义了一个结构体,B文件可以对A中定义的结构体进行访问和修改数据。

    1、 在A.h中定义结构体

    Typedef struct SCI

    {

    U8 data[MAXLEN];

    U16 pos;

    }TSCI;

    2、在A.c文件中声明一个结构体变量

    TSCI Sci;

    3、要实现B.c文件能够调用A中的结构体,需要做到两点:

    (1)在B.h中包含A.h头文件;

    (2)A.c中实现返回结构体变量地址的函数。

     实现函数如下:
    

    TSCI * Get_Address(void) //返回结构体变量的地址 (此TSCI结构体须在A.h中定义)

    {

    Return &Sci;
    

    }

    (4)在B.c中定义一个结构体指针变量,通过调用Get_Address函数得到Sci的地址,将此地址赋给B.h中定义的结构体指针变量。

     TSCI *pSci2;
    
     pSci2 = Get_Address();
    
     pSci2->data[pSci2->pos++]=num;
    
    
    
     这样就可以实现对A.c中的结构体变量Sci的数据访问、修改。
    
    展开全文
  • 结构体指针变量主讲人张静例如有如下定义struct student stu*s=&stu;则以下语句均是合法的strcpy(s->num,11201*s.age=20;stu.sex=M;注意*s)两侧的括号不可少因为成员符.的优先级高于*如去掉括号写作*s.num则等效于(s...
  • 结构体指针

    2019-02-26 14:23:19
    结构体指针实现的串口功能程序,《边学边用攻破C语言》第21集 结构体指针
  • 请问结构体a包含一个结构体指针b,请问使用a时如何初始化?我的使用时总是提示访问冲突。。。谢谢!
  • 结构体指针,C语言结构体指针详解

    千次阅读 2019-06-11 19:15:12
    指向结构体变量的指针 #include <stdio.h> # include <string.h> struct AGE { int year; int month; int day; }; struct STUDENT { char name[20]; //姓名 int num; //学号 struct AGE birthday; //...

    指向结构体变量的指针

    #include <stdio.h>

    # include <string.h>

    struct AGE
    {
    int year;
    int month;
    int day;
    };
    struct STUDENT
    {
    char name[20]; //姓名
    int num; //学号
    struct AGE birthday; //生日
    float score; //分数
    };
    int main(void)
    {
    struct STUDENT student1; /用struct STUDENT结构体类型定义结构体变量student1/
    struct STUDENT *p = NULL; /定义一个指向struct STUDENT结构体类型的指针变量p/
    p = &student1; /p指向结构体变量student1的首地址, 即第一个成员的地址/
    strcpy((*p).name, “小明”); //(*p).name等价于student1.name
    (*p).birthday.year = 1989;
    (*p).birthday.month = 3;
    (p).birthday.day = 29;
    (p).num = 1207041;
    (p).score = 100;

    printf(“name : %s\n”, (*p).name); //(*p).name不能写成p
    printf(“birthday : %d-%d-%d\n”, (*p).birthday.year, (*p).birthday.month, (*p).birthday.day);
    printf(“num : %d\n”, (*p).num);
    printf(“score : %.1f\n”, (*p).score);
    return 0;
    }
    输出结果是:
    name : 小明
    birthday : 1989-3-29
    num : 1207041
    score : 100.0

    我们看到,用指针引用结构体变量成员的方式是:
    (*指针变量名).成员名
    注意,p 两边的括号不可省略,因为成员运算符“.”的优先级高于指针运算符“”,所以如果 *p 两边的括号省略的话,那么 *p.num 就等价于 *(p.num) 了。

    从该程序也可以看出:因为指针变量 p 指向的是结构体变量 student1 第一个成员的地址,即字符数组 name 的首地址,所以 p 和 (*p).name 是等价的。

    但是,“等价”仅仅是说它们表示的是同一个内存单元的地址,但它们的类型是不同的。指针变量 p 是 struct STUDENT* 型的,而 (p).name 是 char 型的。所以在 strcpy 中不能将 (*p).name 改成 p。用 %s 进行输入或输出时,输入参数或输出参数也只能写成 (*p).name 而不能写成 p。

    同样,虽然 &student1 和 student1.name 表示的是同一个内存单元的地址,但它们的类型是不同的。&student1 是 struct STUDENT* 型的,而 student1.name 是 char* 型的,所以在对 p 进行初始化时,“p=&student1;”不能写成“p=student1.name”。因为 p 是 struct STUDENT* 型的,所以不能将 char* 型的 student1.name 赋给 p。

    此外为了使用的方便和直观,用指针引用结构体变量成员的方式:
    (*指针变量名).成员名
    可以直接用:
    指针变量名->成员名
    来代替,它们是等价的。“->”是“指向结构体成员运算符”,它的优先级同结构体成员运算符“.”一样高。p->num 的含义是:指针变量 p 所指向的结构体变量中的 num 成员。p->num 最终代表的就是 num 这个成员中的内容。

    include <stdio.h>

    include <string.h>

    struct AGE
    {
    int year;
    int month;
    int day;
    };
    struct STUDENT
    {
    char name[20]; //姓名
    int num; //学号
    struct AGE birthday; /用struct AGE结构体类型定义结构体变量birthday, 生日/
    float score; //分数
    };
    int main(void)
    {
    struct STUDENT student1; /用struct STUDENT结构体类型定义结构体变量student1/
    struct STUDENT *p = NULL; /定义struct STUDENT结构体类型的指针变量p/
    p = &student1; /p指向结构体变量student1的首地址, 即第一项的地址/
    strcpy(p->name, “小明”);
    p->birthday.year = 1989;
    p->birthday.month = 3;
    p->birthday.day = 29;
    p->num = 1207041;
    p->score = 100;
    printf(“name : %s\n”, p->name); //p->name不能写成p
    printf(“birthday : %d-%d-%d\n”, p->birthday.year, p->birthday.month, p->birthday.day);
    printf(“num : %d\n”, p->num);
    printf(“score : %.1f\n”, p->score);
    return 0;
    }
    输出结果是:
    name : 小明
    birthday : 1989-3-29
    num : 1207041
    score : 100.0

    但是要注意的是,只有“指针变量名”后面才能加“->”,千万不要在成员名如 birthday 后面加“->”。
    综上所述,以下 3 种形式是等价的:
    结构体变量.成员名。
    (*指针变量).成员名。
    指针变量->成员名。
    其中第 3 种方式很重要,通常都是使用这种方式,另外两种方式用得不多。后面讲链表的时候用的也都是第 3 种方式。

    指向结构体数组的指针
    在前面讲数值型数组的时候可以将数组名赋给一个指针变量,从而使该指针变量指向数组的首地址,然后用指针访问数组的元素。结构体数组也是数组,所以同样可以这么做。

    我们知道,结构体数组的每一个元素都是一个结构体变量。如果定义一个结构体指针变量并把结构体数组的数组名赋给这个指针变量的话,就意味着将结构体数组的第一个元素,即第一个结构体变量的地址,也即第一个结构变量中的第一个成员的地址赋给了这个指针变量。

    include <stdio.h>

    struct STU
    {
    char name[20];
    int age;
    char sex;
    char num[20];
    };
    int main(void)
    {
    struct STU stu[5] = {{“小红”, 22, ‘F’, “Z1207031”}, {“小明”, 21, ‘M’, “Z1207035”}, {“小七”, 23, ‘F’, “Z1207022”}};
    struct STU *p = stu;
    return 0;
    }
    此时指针变量 p 就指向了结构体数组的第一个元素,即指向 stu[0]。我们知道,当一个指针指向一个数组后,指针就可以通过移动的方式指向数组的其他元素。

    这个原则对结构体数组和结构体指针同样适用,所以 p+1 就指向 stu[1] 的首地址;p+2 就指向 stu[2] 的首地址……所以只要利用 for 循环,指针就能一个个地指向结构体数组元素。
    同样需要注意的是,要将一个结构体数组名赋给一个结构体指针变量,那么它们的结构体类型必须相同

    include <stdio.h>

    struct STU
    {
    char name[20];
    int age;
    char sex;
    char num[20];
    };
    int main(void)
    {
    struct STU stu[3] = {{“小红”, 22, ‘F’, “Z1207031”}, {“小明”, 21, ‘M’, “Z1207035”}, {“小七”, 23, ‘F’, “Z1207022”}};
    struct STU *p = stu;
    for (; p<stu+3; ++p)
    {
    printf(“name:%s; age:%d; sex:%c; num:%s\n”, p->name, p->age, p->sex, p->num);
    }
    return 0;
    }
    输出结果是:
    name:小红; age:22; sex:F; num:Z1207031
    name:小明; age:21; sex:M; num:Z1207035
    name:小七; age:23; sex:F; num:Z1207022

    此外同前面“普通数组和指针的关系”一样,当指针变量 p 指向 stu[0] 时,p[0] 就等价于 stu[0];p[1] 就等价于 stu[1];p[2] 就等价于 stu[2]……所以 stu[0].num 就可以写成 p[0].num,其他同理。下面将上面的程序用 p[i] 的方式修改一下:

    include <stdio.h>

    struct STU
    {
    char name[20];
    int age;
    char sex;
    char num[20];
    };
    int main(void)
    {
    struct STU stu[3] = {{“小红”, 22, ‘F’, “Z1207031”}, {“小明”, 21, ‘M’, “Z1207035”}, {“小七”, 23, ‘F’, “Z1207022”}};
    struct STU *p = stu;
    int i = 0;
    for (; i<3; ++i)
    {
    printf(“name:%s; age:%d; sex:%c; num:%s\n”, p[i].name, p[i].age, p[i].sex, p[i].num);
    }
    return 0;
    }

    输出结果是:
    name:小红; age:22; sex:F; num:Z1207031
    name:小明; age:21; sex:M; num:Z1207035
    name:小七; age:23; sex:F; num:Z1207022

    展开全文
  • c++根据结构体成员指针找到结构体指针

    千次阅读 多人点赞 2013-07-17 23:54:00
    使用宏CONTAINING_RECORD,可以直接根据结构体成员指针找到结构体指针。为什么这样就能得到结构体指针?这个得益于结构体在申请内存空间是一段连续的地址,我们可以通过其中某个成员变量的地址,减去该成员的偏移来...
  • 结构体指针变量的值是所指向的结构体变量的起始地址。通过结构体指针即可访问该结构体变量,这与数组指针和函数指针的情况是相同的。 结构体指针变量定义的一般形式: 结构体名 *结构体指针变量名 当然也可以在...
  • struct T ** ptr, 说白了 就是一个结构体指针的数组,数组内都是指针,还要分配内存。 1,结构体指针用法一: struSysInfo *SysInfo; SysInfo = (struSysInfo*)malloc(sizeof(struSysInfo)); SysInfo->...
  • 结构体指针 与 结构体成员指针

    千次阅读 2018-12-23 11:39:05
    一、结构体指针: struct A //结构体类型名A { int a; float b; }m; //结构体变量名m int *p=&amp;amp;m //定义结构体指针并指向结构体 二、结构体成员指针: struct B //定义结构体类型名B { ...
  • C语言中的结构体指针

    千次阅读 多人点赞 2017-01-16 23:45:08
    结构体指针的概念概念:结构体变量的地址,指向某个结构体变量(同时也是结构体变量中第一个元素的地址),我们可以通过结构体变量可以指向结构体中包含的一些成员定义: struct 结构体名 *结构体指针变量名;...
  • C语言结构体与结构体指针的使用

    千次阅读 多人点赞 2020-08-08 22:29:02
    C语言结构体与结构体指针的使用 tips:最近要好好学习一下数据结构,所以必不可少的就是c语言的结构体和结构体指针了,所以就整理一下这些基础知识 c语言结构体(struct)是由一系列具有相同类型或不同类型的数据构成...
  • 文章目录1.前言2.内存空间上面的差别3.访问上的差别 ...结构体指针p是指向一个结构体的,这个结构体没有名字,它指向的是一个结构体空间的首地址;如果需要使用这个结构体就必须malloc一个空间出来或者将一个
  • 请问 如果定义了结构体指针不分配内存会怎样 请问 如果定义了结构体指针不分配内存会怎样
  • 结构体和结构体指针

    2019-11-09 21:11:58
    可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址(也就是说你可能有很多个变量,但是这些变量有一个其实地址,那么此时这个结构体指针变量指向的就是这个起始地址)。...
  • C语言 C++两个版本 txt 文件读取结构体信息,写入结构体指针中,并以结构体指针形式返回 附加功能:采用 直接插入排序 方法 按总成绩进行了降序排序 1、结构体信息如下: #define size 9 struct student//学生...
  • 结构体 结构体: 一系列不同类型的数据的结合 强调:类型!= 变量。 结构体名代表的只是结构体类型,没有内存空间。 结构体中的成员可以单独使用 1 定义结构体 struct Studet { char name[20]; int age; char ...
  • 当函数的形参为结构体指针,但是在函数中不仅修改指针指向的值,而且修改指针指向的地址 以下可以改变主函数中a的值,但是a指向的地址不会发生改变 struct student { int aa; int bb; student() {} student(int ...
  • 文章目录结构体嵌套结构体数组初始化结构体数组结构体指针指针访问成员方法 结构体嵌套 比如上篇博客的代码 struct Book { char title[128]; char author[40]; float price; unsigned int date; char ...
  • 结构体指针和结构体嵌套

    千次阅读 2016-02-23 19:04:04
    原文 ... ...结构体指针 ...当一个指针指向一个结构体变量的时候,就叫做结构体指针,结构体指针指向结构体变量的首地址 访问成员值: #include int main(int argc, const char * argv[]) { str
  • 结构体变量和结构体指针的区别,

    千次阅读 多人点赞 2019-06-23 13:11:44
    而指向运算符则是结构体指针访问成员时使用的,因为一直都是再用结构体指针,突然用结构体变量,使用了指向运算符,看了半天才看出来,当然结构体指针也可以使用成员运算符但需要先取值,但一般没人这么用, ...
  • 在 计算结构体中某个元素相对结构体首字节地址的偏移量 基础上进行结构体成员指针反推该结构体变量的指针 计算结构体中某个元素相对结构体首字节地址的偏移量:...
  • 结构体指针 &student1 表示结构体变量 student1 的首地址,即 student1 第一个项的地址。如果定义一个指针变量 p 指向这个地址的话,p 就可以指向结构体变量 student1 中的任意一个成员。 那么,这个指针变量...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 274,808
精华内容 109,923
关键字:

结构体指针指针地址