C语言——结构体

前言

结构(structure 是一种用户自定义的数据类型,用于存储多个不同类型的数据项

一、自定义类型:结构体

数组由数据类型相同的一系列元素组成;结构(structure)是一种用户自定义的数据类型,用于存储多个不同类型的数据项,在内存中连续存放

结构可以看作是另一种数组

1.声明结构体

结构体类型的声明就是告诉编译器结构布局,告诉编译器如何表示数据,但并不让编译器为数据分配空间

一般形式为:

struct  结构体名
{
    数据类型 成员名1;
    数据类型 成员名2;
    ...
    数据类型 成员名n;//结构成员列表
};

例如,下面声明一个学生的结构:

struct Student
{
    char name[20];//姓名
    char sex[10];//性别
    int age;//年龄
    char id[20];//学号
};

2.定义结构体变量

一般形式为:

struct 结构体名 变量名;

例如,下面定义一个学生结构体的变量 s1:

struct Student
{
    char name[20];//姓名
    char sex[10];//性别
    int age;//年龄
    char id[20];//学号
};

struct Student s1;
  • 表示创建了一个结构变量 s1,该变量的结构布局时 Student
  • 编译器以结构布局 Student 为创建的结构变量 s1 分配空间

一般的定义结构体变量的三种方式

(1)在声明结构体后定义结构体变量
struct Student
{
    char name[20];
    char sex[10];
    int age;
    char id[20];
};
struct Student s1,s2,*p1;
(2)声明结构体的同时定义结构体变量
struct Student
{
    char name[20];
    char sex[10];
    int age;
    char id[20];
}s3,s4,*p2;
(3)省略结构体名定义结构体变量
struct
{
    char name[20];
    char sex[10];
    int age;
    char id[20];
}s5;

这种方法只能定义一次结构体变量,它是直接定义结构体变量

第三种定义与其它两种的类型是完全不同的,即使成员列表是一样的,若令 p2=s5,则是非法的

3.初始化

结构体变量定义时初始化

struct Stu s1={"Pit","M",18,"1234"};
//声明结构体后定义结构体变量并赋初值
#include<stdio.h>
struct Student
{
    char name[20];
    char sex[10];
    int age;
    char id[20];
};
struct Student s1 = { "Pit", "M", 18, "1234" };

int main()
{
    printf("%s\t%s\t%d\t%s\n", s1.name, s1.sex, s1.age, s1.id);
    //test
    return 0;
}
//声明结构体的同时定义结构体变量并赋初值
#include<stdio.h>
struct Student
{
    char name[20];
    char sex[10];
    int age;
    char id[20];
}s1 = { "Pit", "M", 18, "1234" };

int main()
{
    printf("%s\t%s\t%d\t%s\n", s1.name, s1.sex, s1.age, s1.id);
    //test
    return 0;
}

在这里插入图片描述

另外有指定初始化器,使用点运算符和成员名标识特定的元素
例如:只初始化Student结构的age成员:

struct Student s1 = { .age = 20 };

也可以按照任意顺序使用指定初始化器,例如:

struct Student s1 = { .age = 20,
	.id = "1234",
	.sex = "M",
	.name = "Pit" };

(2)字符数组

4.字符串拷贝对结构体成员字符数组赋值

字符串拷贝: strcpy(成员,字符串) (记得加头文件 #include<string.h>)

strcpy(s1.name, "Pit");
strcpy(s1.sex, "M");
strcpy(s1.id, "1234");

5.访问结构体成员

结构成员访问运算符 “.” 和 “->”

(1)“.”

一般形式:结构体变量名.成员名

例如:s1.name

(2)“->”

一般形式:结构指针变量->成员名

例如:ps1->name

#include<stdio.h>
struct Student
{
    char name[20];
    char sex[10];
    int age;
    char id[20];
};
struct Student s1 = { "Pit", "M", 18, "1234" };

int main()
{
    struct Student* ps1 = &s1;    //结构指针变量ps1指向结构体变量s1
    printf("%s\n", s1.name);
    printf("%s\n", (*ps1).name);    //*ps1=s1
    printf("%s\n", ps1->name);
}

在这里插入图片描述

二、typedef 定义结构体类型别名

一般形式为:

typedef struct 结构体名 别名;
typedef struct 结构体名//结构体名可以省略
{
    //成员列表
}别名;

例如,下面定义学生结构体的别名 stu,然后定义结构体变量:

typedef struct Student//Student可以省略
{
    char name[20];
    char sex[10];
    int age;
    char id[20];
}stu;
stu s1,* p1;//直接用别名 stu 代替 struct Student

注意在C语言中,上例的用 typedef 起别名 stu 之后就不能以 struct Student s1 来声明结构变量了

上面的结构体名 Student 可以省略,原因是它并不是创建一个结构体变量,而是创建一个标签

注意typedef 起的别名的用法和 define 的简单的直接替换是有区别的

三、结构作为函数参数

#include <stdio.h>
#include <string.h>

struct Student
{
    char name[20];
    char sex[10];
    int age;
    char id[20];
};//结构体声明,不占用存储空间

void printStudent(struct Student s);

int main()
{
    struct Student s1 = { 0 };//定义结构体变量 学生s1

    /* 指定学生 s1 的信息 */
    strcpy(s1.name, "Pit");
    strcpy(s1.sex, "M");
    s1.age = 18;
    strcpy(s1.id, "1234");

    /* 输出学生 s1 的信息 */
    printStudent(s1);

    return 0;
}
void printStudent(struct Student s)
{
    printf("Student name: %s\n", s.name);
    printf("Student sex: %s\n", s.sex);
    printf("Student age: %d\n", s.age);
    printf("Student id: %s\n", s.id);
}

在这里插入图片描述

另外,上面打印学生信息的函数 printStudent 可以改为地址传参的形式:

void printStudent(const struct Student* p)
//(const在*左边,表示指针指向的内容不能通过指针来改变)
{
    printf("Student name: %s\n", p->name);
    printf("Student sex: %s\n", p->sex);
    printf("Student age: %d\n", p->age);
    printf("Student id: %s\n", p->id);
}

结构体地址传参相比于结构体传参更好

原因是,函数传参的时候,参数是需要压栈的,会有时间和空间的系统开销;如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,这就会导致性能的下降

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青春无限坑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值