精华内容
下载资源
问答
  • C语言结构体指针

    2018-10-04 18:30:42
    结构体指针,C语言结构体指针详解 结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针。 指向结构体变量的指针 前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外...

    结构体指针,C语言结构体指针详解

    结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针。
    指向结构体变量的指针
    前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针。

    前面讲过,&student1 表示结构体变量 student1 的首地址,即 student1 第一个项的地址。如果定义一个指针变量 p 指向这个地址的话,p 就可以指向结构体变量 student1 中的任意一个成员。

    那么,这个指针变量定义成什么类型呢?只能定义成结构体类型,且指向什么结构体类型的结构体变量,就要定义成什么样的结构体类型。比如指向 struct STUDENT 类型的结构体变量,那么指针变量就一定要定义成 struct STUDENT* 类型。

    下面将前面的程序用指针的方式修改一下:

    	# 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语言中几乎可以创建指向任何类型的指针,包括用户自定义的类型。创建结构体指针是极常见的。下面是一个例子:

         1 typedef struct
         2 {
         3     char name[21];
         4     char city[21];
         5     char state[3];
         6 } Rec;
         7 typedef Rec *RecPointer;
         8 
         9 RecPointer r;
        10 r=(RecPointer)malloc(sizeof(Rec));
    

    r是一个指向结构体的指针。请注意,因为r是一个指针,所以像其他指针一样占用4个字节的内存。而malloc语句会从堆上分配45字节的内存。*r是一个结构体,像任何其他Rec类型的结构体一样。下面的代码显示了这个指针变量的典型用法:

        1 strcpy((*r).name, "Leigh");
        2 strcpy((*r).city, "Raleigh");
        3 strcpy((*r).state, "NC");
        4 printf("%sn", (*r).city);
        5 free(r);
    

    您可以像对待一个普通结构体变量那样对待r,但在遇到C的操作符优先级问题时要小心。如果去掉r两边的括号则代码将无法编译,因为“.”操作符的优先级高于“*”操作符。使用结构体指针时不断地输入括号是令人厌烦的,为此C语言引入了一种简记法达到相同的目的:

        1 strcpy(r->name, "Leigh");
    

    r->这种写法和(*r).是完全等效的,但是省去了两个字符。

    指向数组的指针
    还可以创建指向数组的指针,如下所示:

        1     int *p;
        2     int i;
        3 
        4     p=(int *)malloc(sizeof(int[10]));
        5     for (i=0; i<10; i++)
        6         p[i]=0;
        7     free(p);
    

    或:

      1     int *p;
        2     int i;
        3 
        4     p=(int *)malloc(sizeof(int[10]));
        5     for (i=0; i<10; i++)
        6         *(p+i)=0;
        7     free(p);
    
    

    可见要创建指向整数数组的指针,只需创建一个普通的整数指针即可。调用malloc分配合适的数组空间,然后将指针指向数组的第一个元素。访问数组元素既可以用普通的数组下标也可以用指针运算。C将两种方法视为是等效的。

    指向数组的指针这一技巧尤其适用于字符串。您可以为某个特定大小的字符串分配刚好合适的内存。

    指针数组
    有时声明一 个指针数组可以节省大量内存,或者使得某些内存消耗较大的问题得以解决。下面例子中的代码,声明了一个由10个结构体指针组成的数组,而不是一个结构体数组。否则这个结构体数组将占用243 * 10=2,430字节的内存。使用指针数组可以最大限度减小内存消耗,直到用malloc语句为记录实际分配内存空间。作为此过程的演示,下面的代码只为一个记录分配空间,保存某个值后又将空间释放:

    定义一个结构体类型数组,其数组名是数组的首地址,这一点前面的课程介绍得很清楚。
    定义结构体类型的指针,既可以指向数组的元素,也可以指向数组,在使用时要加以区分。

         1     typedef struct
         2     {
         3         char s1[81];
         4         char s2[81];
         5         char s3[81];
         6     } Rec;
         7     Rec *a[10];
         8 
         9     a[0]=(Rec *)malloc(sizeof(Rec));
        10     strcpy(a[0]->s1, "hello");
        11     free(a[0]);
    

    包含指针的结构体
    结构体可以包含指针,如下所示:

         1     typedef struct
         2     {
         3         char name[21];
         4         char city[21];
         5         char phone[21];
         6         char *comment;
         7     } Addr;
         8     Addr s;
         9     char comm[100];
        10 
        11     gets(s.name, 20);
        12     gets(s.city, 20);
        13     gets(s.phone, 20);
        14     gets(comm, 100);
        15     s.comment=
        16      (char *)malloc(sizeof(char[strlen(comm)+1]));
        17     strcpy(s.comment, comm);
    

    只有当评论框里包含有评论的记录时,这一技巧才是有用的。如果没有评论记录,评论框里只包含一个指针(4个字节)。包含评论的记录会分配恰到好处的空间,保存评论的的字符串,这取决于用户输入的字符串的长度。

    指向结构体类型变量的使用
    首先让我们定义结构体:

        1 struct stu
        2 {
        3 char name[20];
        4 long number;
        5 float score[4];
        6 } ;
    

    再定义指向结构体类型变量的指针变量:

    struct stu *p1, *p2 ;
    定义指针变量p 1、p 2,分别指向结构体类型变量。引用形式为:指针变量→成员;
    [例7-2] 对指向结构体类型变量的正确使用。输入一个结构体类型变量的成员,并输出。

        1 #include <stdlib.h> /*使用m a l l o c ( ) 需要* /
         2 struct data / *定义结构体* /
         3 {
         4 int day,month,year;
         5 } ;
         6 struct stu /*定义结构体* /
         7 {
         8 char name[20];
         9 long num;
        10 struct data birthday; /嵌*套的结构体类型成员*/
        11 } ;
        12 main() /*定义m a i n ( ) 函数* /
        13 {
        14 struct stu *student; 定/*义结构体类型指针*/
        15 student=malloc(sizeof(struct stu));/* 针变量分配安全的地址*/
        16 printf("Input name,number,year,month,day:/n");
        17 scanf("%s",student->name);/*入学生姓名、学号、出生年月日*/
        18 scanf("%ld",&student->num);
        19 scanf("%d%d%d",&student->birthday.year,&student->birthday.month,
        20 &student->birthday.day);
        21 printf("/nOutputname,number,year,month,day/n");
        22 /*打印输出各成员项的值*/
        23 printf("%20s%10ld%10d//%d//%d/n",student->name,student->num,
        24 student->birthday.year,student->birthday.month,
        25 student->birthday.day);
        26 }
    

    程序中使用结构体类型指针引用结构体变量的成员,需要通过C提供的函数malloc()来为
    指针分配安全的地址。函数sizeof()返回值是计算给定数据类型所占内存的字节数。指针所指
    各成员形式为:

        1 student->name
        2 student->num
        3 student->birthday.year
        4 student->birthday.month
        5 student->birthday.day
    

    指向结构体类型数组的指针的使用
    定义一个结构体类型数组,其数组名是数组的首地址,这一点前面的课程介绍得很清楚。
    定义结构体类型的指针,既可以指向数组的元素,也可以指向数组,在使用时要加以区分。
    [例7-3] 在例7 - 2中定义了结构体类型,根据此类型再定义结构体数组及指向结构体类型的指针。

         1 struct data
         2 {
         3 intday,month,year;
         4 };
         5 struct stu/*定义结构体*/
         6 {
         7 char name[20];
         8 long num;
         9 struct data birthday;/*套的结构体类型成员*/
        10 };
        11 struct stustudent[4],*p;/*义结构体数组及指向结构体类型的指针*/
    

    作p=student,此时指针p就指向了结构体数组student。
    p是指向一维结构体数组的指针,对数组元素的引用可采用三种方法。
    1)地址法
    student+i和p+i均表示数组第i个元素的地址,数组元素各成员的引用形式为:
    (student+i)->name、(student+i)->num和(p+i)->name、(p+i)->num等。student+i和p+i
    与&student[i]意义相同。
    2)指针法
    若p指向数组的某一个元素,则p++就指向其后续元素。
    3)指针的数组表示法
    若p=student,我们说指针p指向数组student,p[i]表示数组的第i个元素,其效果与
    student[i]等同。对数组成员的引用描述为:p[i].name、p[i].num等。
    [例7-4]指向结构体数组的指针变量的使用。

         1 structdata/*定义结构体类型*/
         2 {
         3 intday,month,year;
         4 };
         5 structstu/*定义结构体类型*/
         6 {
         7 char name[20];
         8 long num;
         9 struct data birthday;
        10 };
        11 main()
        12 {inti;
        13 structstu*p,student[4]={{"liying",1,1978,5,23},{"wangping",2,1979,3,14},
        14 {"libo",3,1980,5,6},{"xuyan",4,1980,4,21}};
        15 /*定义结构体数组并初始化*/
        16 p=student;/*将数组的首地址赋值给指针p,p指向了一维数组student*/
        17 printf("/n1----Outputname,number,year,month,day/n");
        18 for(i=0;i<4;i++)/*采用指针法输出数组元素的各成员*/
        19 printf("%20s%10ld%10d//%d//%d/n",(p+i)->name,(p+i)->num,
        20 (p+i)->birthday.year,(p+i)->birthday.month,
        21 (p+i)->birthday.day);
        22 }
    

    ====================
    再次加深对结构体的理解

        #include<stdio.h>
        #include<stdlib.h>
        typedef struct student *stu;
        struct student
        {
        	int id;
        	int score;
        };
        int main()
        {
        //	stu=(student *)malloc(sizeof(student));     错误表示法
        //	(*stu).id=324;
        //	(*stu).score=100;
        	
        	stu student1=(student *)malloc(sizeof(stu));
        	(*student1).id=324;
        	(*student1).score=100;
        	printf("id=%d score=%d\n",(*student1).id,(*student1).score);
        	printf("id=%d score=%d\n",student1->id,student1->score);
        } 
    
    展开全文
  • c语言结构体指针

    千次阅读 2018-04-24 15:09:42
    结构体指针前,先说一下.号和->的区别 记得当初刚学C语言的时候,搞不清结构体的 . 号和 ->,经常混淆二者的使用。 那么在C语言中. 号是成员访问运算符,当我们需要访问结构的成员的时候,就会使用到它 ...

    写结构体指针前,先说一下 号和 -> 的区别

    记得当初刚学C语言的时候,搞不清结构体的 . 号和 -> ,经常混淆二者的使用。

    那么在C语言中 . 号是成员访问运算符,当我们需要访问结构的成员的时候,就会使用到它

    而当我们需要使用结构体指针来访问结构成员的时候,就得使用->运算符了

    结构体指针栗子:

    ​#include<stdio.h>
    #include<string.h>
     
    typedef struct student{
    int id;
    char name[10];
    char sex;
    }stu;   //结构体别名
     
    void PrintStu(stu *student);
    int main()
    {
        //结构体对象
        stu stu1;
        printf("sizeof of stu1 is:%d\n",sizeof(stu1));
        stu1.id=2014;
        strcpy(stu1.name,"zhangfei");
        stu1.sex='m'; 
        PrintStu(&stu1); 
    
        printf("***************\n");
    
    	//结构体指针
    	stu *s = (stu*)malloc(sizeof(stu)); //申请堆内存
    	s->id = 2018;
    	strcpy(s->name, "zhangfei");
    	s->sex = 'g';
    	PrintStu(s);
     
        return 0;
    }
    void PrintStu(stu *student)
    {
        printf("stu1 id is :%d\n",student->id);
        printf("stu1 name is :%s\n",student->name);
        printf("stu1 sex is :%c\n",student->sex);
     
    }
    
    ​

    结构体指针,就是指向结构体的指针。

    解释C函数中的形参:

    void PrintStu(stu *student)中的形参stu *student,说通俗点就是用来接住外部传来的地址&stu1。

    即 stu *student=&stu1; student可以取其他名字,形参并不是固定的。

    下一篇 C语言字符串函数

    因为工作比较忙csdn不是经常上,如果大家有任何疑问或者找我聊技术唠唠嗑,欢迎加我微信a5230gxkd交流,一起进步,我会第一时间回复

    或者在公众号领取珍藏电子书(带书签)(有c、c++、python、linux、设计模式等),以及c、c++的面试试题和面试技巧。

    展开全文
  • C语言 结构体指针

    千次阅读 多人点赞 2019-06-14 11:21:41
    当一个指针变量指向结构体时,我们就称它为结构体指针 struct 结构体名 *变量名; //结构体 struct stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在小组 float score; //成绩 } ...

    当一个指针变量指向结构体时,我们就称它为结构体指针

    struct 结构体名 *变量名;

    //结构体
    struct stu{
        char *name;  //姓名
        int num;  //学号
        int age;  //年龄
        char group;  //所在小组
        float score;  //成绩
    } stu1 = { "Tom", 12, 18, 'A', 136.5 };
    //结构体指针
    struct stu *pstu = &stu1;
    

    也可以在定义结构体的同时定义结构体指针

    struct stu{
        char *name;  //姓名
        int num;  //学号
        int age;  //年龄
        char group;  //所在小组
        float score;  //成绩
    } stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
    

    结构体变量名和数组名不同,数组名在表达式中会被转换为数组指针,而结构体变量名不会,无论在任何表达式中它表示的都是整个集合本身,要想取得结构体变量的地址,必须在前面加&,所以给 pstu 赋值只能写作:
    struct stu *pstu = &stu1;
    而不能写作:
    struct stu *pstu = stu1;

    还应该注意,结构体和结构体变量是两个不同的概念:结构体是一种数据类型,是一种创建变量的模板,编译器不会为它分配内存空间,就像 int、float、char 这些关键字本身不占用内存一样;结构体变量才包含实实在在的数据,才需要内存来存储。下面的写法是错误的,不可能去取一个结构体名的地址,也不能将它赋值给其他变量:

    struct stu *pstu = &stu;
    struct stu *pstu = stu;

    获取结构体成员

    (*pointer).memberName
    或者:
    pointer->memberName
    

    第一种写法中,. 的优先级高于 * ,(pointer)两边的括号不能少。如果去掉括号写作pointer.memberName,那么就等效于*(pointer.memberName),这样意义就完全不对了。

    第二种写法中,->是一个新的运算符,习惯称它为“箭头”,有了它,可以通过结构体指针直接取得结构体成员;这也是->在C语言中的唯一用途。

    结构体指针的使用

    #include <stdio.h>
    int main(){
        struct{
            char *name;  //姓名
            int num;  //学号
            int age;  //年龄
            char group;  //所在小组
            float score;  //成绩
        } stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
        //读取结构体成员的值
        printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
        printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);
        return 0;
    }
    

    运行结果:

    Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!
    Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!

    ### 结构体数组指针的使用
    ```c
    #include <stdio.h>
    
    struct stu{
        char *name;  //姓名
        int num;  //学号
        int age;  //年龄
        char group;  //所在小组
        float score;  //成绩
    }stus[] = {
        {"Zhou ping", 5, 18, 'C', 145.0},
        {"Zhang ping", 4, 19, 'A', 130.5},
        {"Liu fang", 1, 18, 'A', 148.5},
        {"Cheng ling", 2, 17, 'F', 139.0},
        {"Wang ming", 3, 17, 'B', 144.5}
    }, *ps;
    
    int main(){
        //求数组长度
        int len = sizeof(stus) / sizeof(struct stu);
        printf("Name\t\tNum\tAge\tGroup\tScore\t\n");
        for(ps=stus; ps<stus+len; ps++){
            printf("%s\t%d\t%d\t%c\t%.1f\n", ps->name, ps->num, ps->age, ps->group, ps->score);
        }
    
        return 0;
    }
    

    运行结果:

    Name Num Age Group Score
    Zhou ping 5 18 C 145.0
    Zhang ping 4 19 A 130.5
    Liu fang 1 18 A 148.5
    Cheng ling 2 17 F 139.0
    Wang ming 3 17 B 144.5

    展开全文
  • C语言结构体指针的定义形式一般为: struct 结构体名 *变量名; 下面是一个定义结构体指针的实例: //结构体 struct stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在小组 ...

    一、结构体指针

    当一个指针变量指向结构体时,我们就称它为结构体指针。C语言结构体指针的定义形式一般为:

    struct 结构体名 *变量名;

    下面是一个定义结构体指针的实例:

    //结构体
    struct stu{
        char *name;  //姓名
        int num;  //学号
        int age;  //年龄
        char group;  //所在小组
        float score;  //成绩
    } stu1 = { "Tom", 12, 18, 'A', 136.5 };
    //结构体指针
    struct stu *pstu = &stu1;

    也可以在定义结构体的同时定义结构体指针:

    struct stu{
        char *name;  //姓名
        int num;  //学号
        int age;  //年龄
        char group;  //所在小组
        float score;  //成绩
    } stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;

    注意,结构体变量名和数组名不同,数组名在表达式中会被转换为数组指针,而结构体变量名不会,无论在任何表达式中它表示的都是整个集合本身,要想取得结构体变量的地址,必须在前面加&,所以给 pstu 赋值只能写作:

    struct stu *pstu = &stu1;

    而不能写作:

    struct stu *pstu = stu1;

    还应该注意,结构体和结构体变量是两个不同的概念:结构体是一种数据类型,是一种创建变量的模板,编译器不会为它分配内存空间,就像 int、float、char 这些关键字本身不占用内存一样;结构体变量才包含实实在在的数据,才需要内存来存储。下面的写法是错误的,不可能去取一个结构体名的地址,也不能将它赋值给其他变量:

    struct stu *pstu = &stu;
    struct stu *pstu = stu;

    二、获取结构体成员

    通过结构体指针可以获取结构体成员,一般形式为:

    (*pointer).memberName

    或者:

    pointer->memberName

    第一种写法中,.的优先级高于*(*pointer)两边的括号不能少。如果去掉括号写作*pointer.memberName,那么就等效于*(pointer.memberName),这样意义就完全不对。

    第二种写法中,->是一个新的运算符,习惯称它为“箭头”,有了它,可以通过结构体指针直接取得结构体成员;这也是->在C语言中的唯一用途。


    上面的两种写法是等效的,我们通常采用后面的写法,这样更加直观。

    【示例】结构体指针的使用。

    #include <stdio.h>
    
    int main()
    {
        struct{
            char *name;  //姓名
            int num;  //学号
            int age;  //年龄
            char group;  //所在小组
            float score;  //成绩
        } stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
    
        //读取结构体成员的值
        printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
        printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);
    
        return 0;
    }

    运行结果:

    Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!
    Tom的学号是12,年龄是18,在A组,今年的成绩是136.5!

    【示例】结构体数组指针的使用。

    #include <stdio.h>
    
    struct stu{
        char *name;  //姓名
        int num;  //学号
        int age;  //年龄
        char group;  //所在小组
        float score;  //成绩
    }stus[] = {
        {"Zhou ping", 5, 18, 'C', 145.0},
        {"Zhang ping", 4, 19, 'A', 130.5},
        {"Liu fang", 1, 18, 'A', 148.5},
        {"Cheng ling", 2, 17, 'F', 139.0},
        {"Wang ming", 3, 17, 'B', 144.5}
    }, *ps;
    
    int main()
    {
        //求数组长度
        int len = sizeof(stus) / sizeof(struct stu);
        printf("Name\t\tNum\tAge\tGroup\tScore\t\n");
        for(ps=stus; ps<stus+len; ps++){
            printf("%s\t%d\t%d\t%c\t%.1f\n", ps->name, ps->num, ps->age, ps->group, ps->score);
        }
    
        return 0;
    }

    运行结果:

    Name            Num     Age     Group   Score
    Zhou ping       5       18      C       145.0
    Zhang ping      4       19      A       130.5
    Liu fang        1       18      A       148.5
    Cheng ling      2       17      F       139.0
    Wang ming       3       17      B       144.5

    三、结构体指针作为函数参数

    结构体变量名代表的是整个集合本身,作为函数参数时传递的整个集合,也就是所有成员,而不是像数组一样被编译器转换成一个指针。如果结构体成员较多,尤其是成员为数组时,传送的时间和空间开销会很大,影响程序的运行效率。所以最好的办法就是使用结构体指针,这时由实参传向形参的只是一个地址,非常快速。

    【示例】计算全班学生的总成绩、平均成绩和以及 140 分以下的人数。

    #include <stdio.h>
    
    struct stu{
        char *name;  //姓名
        int num;  //学号
        int age;  //年龄
        char group;  //所在小组
        float score;  //成绩
    }stus[] = {
        {"Li ping", 5, 18, 'C', 145.0},
        {"Zhang ping", 4, 19, 'A', 130.5},
        {"He fang", 1, 18, 'A', 148.5},
        {"Cheng ling", 2, 17, 'F', 139.0},
        {"Wang ming", 3, 17, 'B', 144.5}
    };
    
    void average(struct stu *ps, int len);
    
    int main()
    {
        int len = sizeof(stus) / sizeof(struct stu);
        average(stus, len);
        return 0;
    }
    
    void average(struct stu *ps, int len)
    {
        int i, num_140 = 0;
        float average, sum = 0;
        for(i=0; i<len; i++){
            sum += (ps + i) -> score;
            if((ps + i)->score < 140) num_140++;
        }
        printf("sum=%.2f\naverage=%.2f\nnum_140=%d\n", sum, sum/5, num_140);
    }

    运行结果:

    sum=707.50
    average=141.50
    num_140=2

     

    展开全文
  • 当一个指针变量指向结构体时,我们就称它为C语言结构体指针的定义形式一般为:struct 结构体名 *变量名;下面是一个定义结构体指针的实例://结构体struct stu{char *name; //姓名int num; //学号int age; //年龄char...
  • 当一个指针变量指向结构体时,我们就称它为C语言结构体指针的定义形式一般为:struct 结构体名 *变量名;下面是一个定义结构体指针的实例://结构体struct stu{char *name; //姓名int num; //学号int age; //年龄char...
  • C语言结构体指针(指向结构体的指针)详解 当一个指针变量指向结构体时,我们就称它为结构体指针。C语言结构体指针的定义形式一般为: struct 结构体名 *变量名; 下面是一个定义结构体指针的实例:(写法1:分开...
  • C语言结构体,C语言结构体指针,java对象引用,传值,传地址,传引用 传值 把实参的值赋值给行参 那么对行参的修改,不会影响实参的值 传地址 传值的一种特殊方式,只是他传递的是地址,不是普通的如int 那么传地址...
  • 结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针。指向结构体变量的指针前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针。前面讲过,&...
  • 结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针。 指向结构体变量的指针 前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针。 前面讲过,&...
  • c语言结构体指针初始化 今天来讨论一下C中的内存管理。 记得上周在饭桌上和同事讨论C语言的崛起时,讲到了内存管理方面 我说所有指针使用前都必须初始化,结构体中的成员指针也是一样 有人反驳说,...
  • C语言结构体指针,函数指针的用法

    千次阅读 2014-12-18 23:35:14
    学习一下,保证自己的基础,...第一个程序是:C语言结构体指针用法,包括malloc和free的用法 #include "stdafx.h" #include #include using namespace std; struct People{ int age; char *c; }; int main() {

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,840
精华内容 2,736
关键字:

c语言结构体指针

c语言 订阅