结构体成员的访问和传参

文章介绍了C语言中结构体的基础知识,包括如何声明结构体,通过点操作符访问结构体成员,以及使用结构体指针。在主函数中展示了如何初始化结构体变量并打印其成员。此外,文章还讨论了在函数传参时,为避免大结构体带来的开销,通常传递结构体的地址而非整个结构体。最后,给出了两个示例函数来展示这两种传参方式。

一、基础知识
1、声明

struct stu
{
 char name[10];
 int age;
 char sex;
 char id[20];
};

结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量比如数组,指针甚至是其他结构体
二、访问
结构体变量访问成员
结构变量的成员是通过点操作符(.)访问的,点操作符接受两个操作数,例如

#include<stdio.h>
#include<string.h>
struct stu
{
 char name[10];
 int age;
 char sex;
 char id[20];
};
int main()
{
 struct stu s1 = { "yao",77,'1',"39999" };
 printf("%s\n", s1.id);
 strcpy(s1.id, "222222");
 printf("%s\n", s1.id);
}

结构体指针访问成员

#include<stdio.h>
struct stu
 {
  char name[10];
  int age;
  char sex;
  char id[20];
 };
int main()
{
 struct stu s1 = { "yao",77,'1',"39999" };
 struct stu* p = &s1;
 printf("%d\n", p->age);
 printf("%d", (*p).age);
 return 0;
}

三、传参函数
传参的时候,参数是需要压栈的,如果传递一个结构体对象的时候,结构体过大,参数压栈系统开销比较大,所以一般传结构体的地址

#include<stdio.h>
struct stu
 {
  char name[10];
  int age;
  char sex;
  char id[20];
 };
void print1(struct stu s)
{
 printf("%d\n", s.age);
}
void print2(struct stu *p)
{
 printf("%d\n", p->age);
}
int main()
{
 struct stu s1 = { "yao",77,'1',"39999" };
 struct stu* p = &s1;
 print1(s1);
 print2(p);
 return 0;
}
<think>我们正在讨论C语言访问结构体不存在的成员导致的错误。 根据C语言的特性,结构体成员是固定的,在编译时就已经确定。如果尝试访问一个结构体中不存在的成员,编译器会报错。 引用中提到: [^1] 介绍了结构体的基本概念,包括声明、自引用、初始化、访问传参内存对齐等。 [^2] 提到了匿名结构体的声明初始化。 [^3] 详细说明了结构体,包括自引用(需要使用指针)以及创建结构体变量的方式。 [^4] 提到了结构体的定义格式以及通过函数访问成员的方法。 问题:访问结构体不存在的成员会导致什么错误? 回答: 在C语言中,结构体成员在定义时确定。如果程序试图访问一个结构体中没有定义的成员,编译器会在编译阶段报错,因为编译器知道该结构体的确切布局。 例如,假设我们有以下结构体定义: ```c struct Person { char name[20]; int age; }; ``` 如果我们尝试访问`gender`成员(该成员不存在): ```c struct Person p; p.gender = 'M'; // 错误:struct Person没有名为gender的成员 ``` 编译器会直接报错,阻止程序生成可执行文件。因此,这种错误在编译时就会被捕获。 但是,如果通过指针进行访问,并且错误地访问了不存在的成员,同样会触发编译错误。 另外,如果使用匿名结构体(如引用[^2]所述),由于结构体没有类型名,我们只能通过变量名来使用,但同样必须访问其实际存在的成员。 总结:访问结构体不存在的成员会导致编译错误,无法通过编译。 相关问题: 1. 如何避免访问结构体不存在的成员? 2. 结构体成员访问方式有哪些? 3. 如果结构体定义在头文件中,如何确保成员访问的一致性? 4. 结构体成员的内存对齐对访问有什么影响?</think>在C语言中,**访问结构体不存在的成员会导致编译错误**,因为编译器会严格检查结构体成员的合法性。这是C语言类型安全机制的重要部分,具体表现如下: ### 错误原理与表现 1. **编译时报错** 编译器在解析代码时会检查结构体成员是否存在。例如: ```c struct Student { char name[20]; int age; }; int main() { struct Student s; s.grade = 90; // 错误:'struct Student' 没有名为 'grade' 的成员 return 0; } ``` 编译器会直接报错:`error: 'struct Student' has no member named 'grade'`,阻止程序生成可执行文件[^1][^4]。 2. **错误类型** - **成员名拼写错误**:如将 `age` 误写为 `aeg` - **成员未定义**:访问未在结构体声明中定义的成员 - **作用域错误**:尝试访问其他结构体类型的成员 --- ### 根本原因:结构体的静态内存布局 1. **固定内存偏移** 结构体成员访问本质上是 **基地址 + 固定偏移量** 的计算。例如: ```c s.age // 编译后实际执行:*(s + offsetof(age)) ``` 若成员不存在,编译器无法计算偏移量[^1][^4]。 2. **内存对齐约束** 结构体遵循严格的内存对齐规则(如4字节对齐)。访问非法成员会破坏对齐规则,导致不可预测行为(如果错误代码意外通过编译)[^1][^4]。 --- ### 规避与调试建议 1. **使用类型检查工具** ```c #define CHECK_MEMBER(struct_type, member) \ (void)sizeof(((struct_type *)0)->member) // 编译期成员检查 ``` 2. **规范开发实践**: - 通过 `get_/set_` 函数封装成员访问[^4] - 使用 `typedef` 明确结构体类型 - 开启编译器警告:`gcc -Wall -Werror` 3. **调试技巧** 当遇到模糊的访问错误时: ```c printf("Member offset: %zu\n", offsetof(struct Student, age)); // 验证偏移量 ``` --- ### 相关问题 1. 如何检测结构体成员是否存在? 2. 结构体内存对齐会如何影响成员访问?[^1][^4] 3. 匿名结构体(未命名结构体)的成员访问有何特殊规则?[^2] 4. 结构体自引用时(如链表节点),如何避免成员访问错误?[^3] [^1]: C语言结构体基础:声明、内存对齐与访问规则 [^2]: 匿名结构体的初始化与成员访问限制 [^3]: 结构体自引用场景下的成员访问安全 [^4]: 通过封装函数规范结构体成员访问
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值