结构体的基本用法

引言

结构体(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字节)。
posted @ 2025-09-26 23:22  开心猪扒  阅读(28)  评论(0)    收藏  举报