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语言结构体指针引用详解的文章就介绍到这了,更多相关C语言 结构体指针内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 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; 也可以在定义结构体的同时定义结构

  • C语言结构体指针案例解析

    写结构体指针前,先说一下 . 号和 -> 的区别 记得当初刚学C语言的时候,搞不清结构体的 . 号和 -> ,经常混淆二者的使用. 那么在C语言中 . 号是成员访问运算符,当我们需要访问结构的成员的时候,就会使用到它 而当我们需要使用结构体指针来访问结构成员的时候,就得使用->运算符了. 结构体指针栗子: ​#include<stdio.h> #include<string.h> typedef struct student{ int id; char name[

  • 详解C语言结构体中的函数指针

    结构体是由一系列具有相同类型或不同类型的数据构成的数据集合.所以,标准C中的结构体是不允许包含成员函数的,当然C++中的结构体对此进行了扩展.那么,我们在C语言的结构体中,只能通过定义函数指针的方式,用函数指针指向相应函数,以此达到调用函数的目的. 函数指针 函数类型 (*指针变量名)(形参列表):第一个括号一定不能少. "函数类型"说明函数的返回类型,由于"()"的优先级高于"*",所以指针变量名外的括号必不可少.  注意指针函数与函数指针表示

  • 深入分析C语言中结构体指针的定义与引用详解

    指向结构体类型变量的使用首先让我们定义结构体:struct stu{char name[20];long number;float score[4];} ;再定义指向结构体类型变量的指针变量:struct stu *p1, *p2 ;定义指针变量p 1.p 2,分别指向结构体类型变量.引用形式为:指针变量→成员:[例7-2] 对指向结构体类型变量的正确使用.输入一个结构体类型变量的成员,并输出. 复制代码 代码如下: #include <stdlib.h> /*使用m a l l o c (

  • C语言结构体指针引用详解

    目录 指向结构体变量的指针 指向结构体数组的指针 结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针. 指向结构体变量的指针 前面我们通过"结构体变量名.成员名"的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针. 前面讲过,&student1 表示结构体变量 student1 的首地址,即 student1 第一个项的地址.如果定义一个指针变量 p 指向这个地址的话,p 就可以指向结构体变量 student1 中的任意一个成员. 那么,这个指针变量定义成

  • C语言结构体,枚举,联合体详解

    目录 1.什么是结构体.枚举.联合体 2.定义结构体 2.1 包含结构体成员变量.variable 2.2 tag.结构体成员变量 2.3 用结构体声名变量 2.4 用typedef 创建新类型 2.5 两个结构体相互包含 2.6 结构体变量初始化 2.7 结构体指针 3.枚举 3.1 定义方式 3.2 为什么用枚举 3.3 枚举变量的定义 3.4 实例 3.5 枚举实际用途 4.联合体 4.1 与结构体区别 4.2 定义 总结 1.什么是结构体.枚举.联合体 结构体(struct)是由一系列具

  • go语言结构体指针操作示例详解

    目录 指针 go指针操作 不能操作不合法指向 new函数 指针做函数的参数 数组指针 结构体指针变量 结构体成员普通变量 结构体成员指针变量 结构体比较和赋值 结构体作为函数参数 指针 指针是代表某个内存地址的值.内存地址储存另一个变量的值. 指针(地址),一旦定义了不可改变,指针指向的值可以改变 go指针操作 1.默认值nil,没有NULL常量 2.操作符“&”取变量地址,“*“通过指针(地址)访问目标对象(指向值) 3.不支持指针运算,不支持“->”(箭头)运算符,直接用“.”访问目标成

  • Go语言基础语法之结构体及方法详解

    结构体类型可以用来保存不同类型的数据,也可以通过方法的形式来声明它的行为.本文将介绍go语言中的结构体和方法,以及"继承"的实现方法. 结构体类型 结构体类型(struct)在go语言中具有重要地位,它是实现go语言面向对象编程的重要工具.go语言中没有类的概念,可以使用结构体实现类似的功能,传统的OOP(Object-Oriented Programming)思想中的继承在go中可以通过嵌入字段的方式实现. 结构体的声明与定义: // 使用关键字 type 和 struct 定义名字

  • Go语言学习教程之结构体的示例详解

    目录 前言 可导出的标识符 嵌入字段 提升 标签 结构体与JSON相互转换 结构体转JSON JSON转结构体 练习代码步骤 前言 结构体是一个序列,包含一些被命名的元素,这些被命名的元素称为字段(field),每个字段有一个名字和一个类型. 结构体用得比较多的地方是声明与数据库交互时需要用到的Model类型,以及与JSON数据进行相互转换.(当然,项目中任何需要多种数据结构组合在一起使用的地方,都可以选择用结构体) 代码段1:声明一个待办事项的Model类型: type Todo struct

  • Go语言同步等待组sync.WaitGroup结构体对象方法详解

    目录 sync.WaitGroup结构体对象 WaitGroup的结构体 Add()方法 Done()方法 Wait()方法 Add().Done().Wait()三者对比 sync.WaitGroup使用示例 sync.WaitGroup结构体对象 在Go语言中,sync.WaitGroup结构体对象用于等待一组线程的结束:WaitGroup是go并发中最常用的工具,我们可以通过WaitGroup来表达这一组协程的任务是否完成,以决定是否继续往下走,或者取任务结果: WaitGroup的结构体

  • C语言结构体内存对齐详解

    目录 实例一: 分析:存储结构图如下 实例二: 分析:存储结构如下 实例三: 分析:存储结构如下 实例四: 分析:存储结构图如下 总结 1.结构体内存对齐是指当我们创建一个结构体变量时,会向内存申请所需的空间,用来存储结构体成员的内容.我们可以将其理解为结构体成员会按照特定的规则来存储数据内容. 2.结构体的对齐规则 (1)第一个成员在相比于结构体变量存储起始位置偏移量为0的地址处. (2)从第二个成员开始,在其自身对齐数的整数倍开始存储(对齐数=编译器默认对齐数和成员字节大小的最小值,VS编译

  • 深入浅析C/C++语言结构体指针的使用注意事项

    主要内容 结构体的使用 - 定义,赋值,结构体指针 结构体作为函数参数的使用 指针的使用 代码内容重点 1.结构体的使用 - 定义,赋值,结构体指针 2.结构体作为函数参数的使用 - 最好使用结构体指针作为参数,而不是结构体 因为当传递的结构体作为参数,数据量较大时,会占用较大的时间与空间,效率很低 使用结构体指针作为函数参数,比用结构体本身作参数效率高很多,当只是读取而不希望修改结构体值时,可以添加const防止改变结构体成员值 (STAFF_T const *p) 3.指针的使用 - 指针的

  • C语言中结构体变量私有化详解

    背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类.结构体可以被声明为变量.指针或数组等,用以实现较复杂的数据结构.结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问. 问题描述 C语言结构体定义中的变量默认是公有(Public)属性,如果实现成员变量的

随机推荐