七,结构体

七,结构体

  1. 结构体类型的声明

  2. 结构体初始化

  3. 结构体成员

  4. 结构体传参

0.前置知识

关于typedef

在C语言中,使用 typedef 关键字可以创建类型别名,也就是为一个已有的数据类型(包括基本类型、结构体、枚举等)赋予一个新的名称。这个新的名称可以用来代替原有的类型名,从而使代码更加清晰、易读和可维护。

通过创建类型别名,我们可以为某个类型提供一个更加具有描述性的名称,或者将复杂的类型声明简化为一个更简单、易于理解的名称。这在代码编写和阅读过程中非常有用,特别是在处理复杂的数据结构、函数指针或回调函数时。

下面是一些示例,展示了如何使用 typedef 创建类型别名:

cCopy codetypedef int MyInt; // 创建一个类型别名 MyInt,代表 int 类型

typedef struct
{
    char name[20];
    int age;
} Person; // 创建一个类型别名 Person,代表结构体类型

typedef void (*Callback)(int); // 创建一个类型别名 Callback,代表函数指针类型

typedef enum
{
    RED,
    GREEN,
    BLUE
} Color; // 创建一个类型别名 Color,代表枚举类型

在这些示例中,通过 typedef 关键字为不同的数据类型创建了新的类型别名。这样,我们可以在后续的代码中直接使用这些别名,而不需要再写出完整的类型名。这有助于提高代码的可读性和可维护性。

例如,使用了类型别名的代码可能会是这样的:

cCopy codeMyInt num = 10;
Person p;
Callback cb;
Color c = RED;

通过使用类型别名,我们可以更加直观地理解代码中的数据类型,并且减少了重复编写冗长类型名的工作。

1.结构体的声明

1.1 结构的基础知识

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量

1.2结构的声明

struct tag//tag是名字
{
	member - list;//成员列表(1个或者多个)
}variable-list;//变量列表

举例说明:

struct Stu
{
	//成员变量,是用来描述结构体对象的相关属性的
	char name[20];
	int age;
	char sex[5];//男 女  保密
} s2,s3,s4; //s2,s3,s4 就是结构体变量 - 全局变量
//这个调用的时候只能写struct Stu

typedef struct Stu1
{
	//成员变量,是用来描述结构体对象的相关属性的
	char name[20];
	int age;
	char sex[5];//男 女  保密
}shiyong;
//这个调用的时候(typedef)定义了结构体struct Stu1为shiyong,所以之后的代码可以写shiyong xx



int main()
{
	//int a = 10;
	struct Stu s1;//局部变量
	shiyong s2;

	return 0;
}

1.3结构成员的类型

结构的成员可以是标量、数组、指针,甚至是其他结构体。

1.4结构体变量的定义和初始化

范例:

struct Point//声明类型
{
	int x;
	int y;
}p1;//同时定义变量p1
struct Point p2;//定义结构体变量p2
struct Point p3 = { x,y };

2.结构体成员的访问

当谈到结构体的访问方式时,通常有两种常见的方式:

通过点操作符(.

通过指针操作符(->

点操作符(.):

点操作符用于直接访问结构体的成员变量。通过结构体变量名和点操作符,可以访问结构体内部的成员变量。

例如,假设我们有一个名为person的结构体,其中包含了nameage两个成员变量。我们可以使用点操作符来访问这些成员变量:

struct Person {
    char name[20];
    int age;
};

int main() 
{
    struct Person person1;
    strcpy(person1.name, "John");
    person1.age = 25;

    printf("Name: %s\n", person1.name);
    printf("Age: %d\n", person1.age);

    return 0;
}

输出结果:

makefileCopy codeName: John
Age: 25

指针操作符(->):

指针操作符用于通过指向结构体的指针访问结构体的成员变量**。如果我们有一个指向结构体的指针,我们可以使用指针操作符访问结构体的成员。**

以下是一个使用指针操作符访问结构体成员的示例:

struct Person 
{
    char name[20];
    int age;
};

int main() 
{
    struct Person person1;
    struct Person *ptr = &person1;

    strcpy(ptr->name, "John");
    ptr->age = 25;

    printf("Name: %s\n", ptr->name);
    printf("Age: %d\n", ptr->age);

    return 0;
}

输出结果与前一个示例相同:

makefileCopy codeName: John
Age: 25

在这个示例中,我们创建了一个指向结构体person1的指针ptr。通过指针操作符**->**,我们可以使用指针来访问结构体的成员变量。

无论是通过点操作符还是指针操作符,两种方式都允许我们访问结构体的成员变量。选择哪种方式取决于我们使用结构体的方式,以及结构体的访问情况(通过变量还是指针)来决定使用哪种操作符。

例1:.访问

#include<stdio.h>
struct S
{
	int a;
	char arr[6];
	int* p;
}s1 = {100, "world", NULL};

struct S s2 = {98, "hehe", NULL};

struct B
{
	char ch[10];
	struct S s;
	double d;
};

int main()
{
	struct S s3 = {.arr="hello", .p = NULL, .a = 1};//. 结构成员访问操作符
	printf("%d %s %p\n", s3.a, s3.arr, s3.p);//. 结构成员访问操作符
	struct B sb = { "hello", {20, "qqq", NULL}, 3.14};
	printf("%s %d %s %p %.2lf\n", sb.ch, sb.s.a, sb.s.arr, sb.s.p, sb.d);
	return 0;
}

例2:思考为什么这里输出的结果为0?

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

struct Stu
{
	char name[20];
	int age;
};

void set_stu(struct Stu t)
{
	t.age = 20;
	//t.name = "张三";//err
	strcpy(t.name, "张三");//字符串拷贝
}

void print_stu(struct Stu t)
{
	printf("%s %d\n", t.name, t.age);
}

int main()
{
	struct Stu s = {0};
	set_stu(s);//设置
	print_stu(s);//呈现
	return 0;
}

答:

  1. 在C语言中,字符串不能通过简单的赋值运算符来赋值给字符数组。字符串是以字符数组的形式表示的,而在C语言中,字符数组是一种特殊的数据类型,不能直接通过赋值运算符来进行字符串的赋值。

2.   在这段代码中,set_stu函数接受一个struct Stu类型的参数t,然后尝试修改tagename成员变量。然而,函数中对t的修改不会影响到main函数中的s结构体变量,因为在set_stu函数中,参数t是按值传递的。

在函数调用时,传递给set_stu函数的是s的一个副本,而不是s本身。因此,函数中对t的修改不会影响到原始的s结构体变量。

set_stu函数结束后,对t的任何修改都会被丢弃,而原始的s结构体变量保持不变。

因此,在print_stu函数中打印s时,s的成员变量仍然是初始值,即0。

改:

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

struct Stu
{
	char name[20];
	int age;
};

void set_stu(struct Stu *t)
{
	t->age = 20;//(*t).age = 20
	strcpy(t->name, "张三");//strcpy((*t).name, "张三")
}

void print_stu(struct Stu t)
{
	printf("%s %d\n", t.name, t.age);
}

int main()
{
	struct Stu s = {0};
	set_stu(&s);
	print_stu(s);
	return 0;
}

3.结构体传参

总结:结构体传参的时候,要传结构体的地址

原因:

函数传参的时候,参数是需要压栈的。

如果传递一个结构体对象的时候,结构体过大,参数压栈的时候系统开销比较大,所以会导致性能下降。

上代码示例:

#include <stdio.h>
struct S
{
	int data[1000];
	int num;
};
struct S s1 = { {1,2,3,4,5},1000 };//全局变量,不会被销毁
//结构体传参方式1
void print1(struct S s11)
{
	printf("%d\n", s11.num);
}
//结构传参方式2(地址传参)
void print2(struct S *ps1)
{
	printf("%d\n", ps1->num);
}
int main()
{
	print1(s1);
	print2(&s1);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值