结构体的基本用法
引言
结构体(struct)是 C/C++ 中用于将不同类型的数据组合成一个整体的复合数据类型,适用于表示具有多个相关属性的对象(如学生、文件、坐标等)
一、结构体的定义
struct 结构体名
{
数据类型 成员1;
数据类型 成员2;
// ... 更多成员
}; // 注意末尾的分号!
//示例:定义一个 “学生” 结构体
// 定义结构体:包含姓名、年龄、成绩三个成员
struct Student
{
char name[20]; // 姓名(字符串)
int age; // 年龄(整数)
float score; // 成绩(浮点数)
};
1.1 typedef 定义结构体
将结构体定义与 typedef 合并,可省略结构体名(匿名结构体),代码更紧凑。
// 方式A:保留结构体名(推荐,便于后续结构体嵌套)
typedef struct Student
{
char name[20];
int age;
} StudentType;
// 方式B:匿名结构体(无法用于自身嵌套,如链表节点)
typedef struct
{
char name[20];
int age;
} StudentType;
// 使用方式相同:
StudentType s2; // 直接用别名声明变量
如果结构体需要自身嵌套(如链表节点、树节点),必须保留结构体名,否则无法在成员中引用自身类型。
// 错误示例:匿名结构体无法自身嵌套
typedef struct
{
int data;
Node* next; // 编译错误:Node尚未定义(匿名结构体无名称)
} Node;
// 正确示例:保留结构体名,支持自身嵌套
typedef struct Node
{
int data;
struct Node* next; // 用结构体名Node引用自身
} Node; // 别名仍为Node,不影响使用
二、结构体变量声明与初始化
定义结构体后,需声明结构体变量才能使用,可在声明时初始化成员。
2.1声明结构体变量
// 方式1:先定义结构体后单独声明
struct Student s1; // 声明一个Student类型的变量s1
// 方式2:定义结构体时同时声明变量(不推荐,不利于复用)
struct Teacher
{
char name[20];
int id;
} t1, t2; // 同时声明t1、t2两个Teacher变量
2.2初始化结构体变量
初始化时需按成员顺序赋值,或通过指定成员名赋值(C99 及以上支持)。
#include <stdio.h>
struct Student {
char name[20];
int age;
float score;
};
int main()
{
// 方式1:按顺序顺序初始化(必须按成员定义顺序)
struct Student s1 = {"张三", 18, 95.5f};
// 方式2:指定成员名初始化(顺序可任意,C99及以上支持)
struct Student s2 =
{
.age = 19,
.name = "李四",
.score = 88.0f
};
return 0;
}
三、结构体成员的访问
通过 . 操作符访问结构体变量的成员;若为结构体指针,则用 -> 操作符。
#include <stdio.h>
#include <string.h> // 用于strcpy函数
struct Student
{
char name[20];
int age;
float score;
};
int main()
{
struct Student s; // 声明变量
struct Student *p = &s; // 声明结构体指针,指向s
// 1. 用 . 操作符访问成员(普通变量)
strcpy(s.name, "王五"); // 字符串赋值需用strcpy
s.age = 20;
s.score = 92.3f;
// 2. 用 -> 操作符访问成员(指针变量)
printf("姓名:%s\n", p->name); // 等价于 (*p).name
printf("年龄:%d\n", p->age); // 等价于 (*p).age
printf("成绩:%.1f\n", p->score);// 等价于 (*p).score
return 0;
}
四、结构体作为函数参数与返回值
结构体可像普通变量一样作为函数参数传递,或作为返回值返回。
#include <stdio.h>
struct Point
{
int x; // x坐标
int y; // y坐标
};
// 函数:计算两个点的和(x1+x2, y1+y2)
struct Point addPoint(struct Point p1, struct Point p2)
{
struct Point result;
result.x = p1.x + p2.x;
result.y = p1.y + p2.y;
return result; // 返回结构体
}
int main()
{
struct Point a = {3, 5};
struct Point b = {2, 7};
struct Point c = addPoint(a, b); // 结构体作为参数传递
printf("点的和:(%d, %d)\n", c.x, c.y); // 输出 (5, 12)
return 0;
}
五、结构体对齐
结构体总大小并非成员大小的简单相加,而是会根据内存对齐规则(成员地址需为自身大小的整数倍)填充空白字节。
struct Demo
{
char c; // 1字节
int i; // 4字节(因对齐,c后会填充3字节)
};
// sizeof(struct Demo) 结果为 8 字节(1+3+4),而非 5 字节。
六、结构体内部定义函数
C 语言的结构体只能包含成员变量,不能直接定义成员函数(GetSize() 放在结构体内部是错误的)。这是 C 语言与 C++ 的核心区别(C++ 结构体可以包含成员函数)。
6.1 C语言实现
#include <stdio.h>
typedef struct st
{
int x;
int y;
} Point; // 结构体别名Point
// 函数定义在结构体外部
int GetSize()
{
return sizeof(struct st); // 或 sizeof(Point),两者等价
}
int main()
{
Point p;
std::cout << "返回值:" << p.GetSize() << std::endl;
return 0;
}
6.2 C++ 实现
#include <iostream>
typedef struct st
{
int x;
int y;
int GetSize()
{
return sizeof(st); // 英文分号,C++支持结构体成员函数
}
} Point;
int main() {
Point p;
std::cout << "返回值:" << p.GetSize() << std::endl;
return 0;
}
6.3 函数 GetSize 的返回值
两种修正后的代码中,GetSize 的返回值均为 8(在绝大多数系统中):
- 结构体 st 包含两个 int 类型成员(x 和 y)。
- 每个 int 类型在常见系统中占 4 字节,且无需内存对齐填充(两个 int 连续排列,总大小为 4 + 4 = 8字节)。

浙公网安备 33010602011771号