C :结构体详解

C语言结构体(struct)超级详解
从最基础到最容易被面试官问到的进阶用法,一次性讲透!

1. 结构体最基础的概念

struct 结构体标签名
{
    类型1  成员名1;
    类型2  成员名2;
    ...
    类型N  成员名N;
};

最常用的三种写法(请牢牢记住这三种写法)

// 写法1(最常用、最推荐)
struct Student
{
    char name[64];
    int age;
    float score;
    char gender;
};

// 写法2(定义类型的同时直接创建变量)
struct Student
{
    char name[64];
    int age;
    float score;
} stu1, stu2, stu3;         // 同时创建了3个变量

// 写法3(匿名结构体 —— 只能用一次)
struct
{
    char name[64];
    int age;
} person1, person2;         // 这种方式最不推荐

2. 结构体变量的几种常见定义方式对比(重要!)

写法是否有类型名可不可以多次创建变量推荐指数备注
struct Student s1;有(Student)可以★★★★★最推荐
struct Student s1 = {..};可以★★★★初始化写法
struct {..} s1;没有只能用一次★☆几乎不用
typedef struct {..} Stu;有(Stu)可以★★★★★非常常用!后面会讲
typedef struct Student Stu;有(Stu是别名)可以★★★★也很常见

3. 结构体内存对齐(★★★面试最爱考)

最核心的两句话

  1. 结构体内存对齐的根本目的提高CPU读取数据的效率(以牺牲一点内存为代价)
  2. 对齐原则(默认规则,绝大多数编译器都遵守):
每个成员相对于结构体首地址的偏移量 必须 是 自身大小 或者 编译器默认对齐数 的整数倍
整个结构体的大小 必须 是 所有成员中最大对齐数的整数倍

常用的对齐数(32/64位系统通常都是这样)

类型自身大小默认对齐数(常见)
char11
short22
int,float44
double88
指针4/84/8
结构体/共用体最大成员的对齐数

经典例题必做(请全部手算一遍)

struct A
{
    char a;      // 1
    int b;       // 4
    double c;    // 8
    short d;     // 2
};

struct B
{
    double c;    // 8
    int b;       // 4
    char a;      // 1
    short d;     // 2
};

struct C
{
    char a;      //1
    struct A b;  // 按照 struct A 整体来算
};

答案(请自己先算,再对):

  • sizeof(struct A) = 24
  • sizeof(struct B) = 16(最优写法)
  • sizeof(struct C) = 48(因为里面嵌套了一个24字节的struct A)

4. 结构体初始化最常见的几种写法

struct Student
{
    char name[64];
    int age;
    float score;
};

// 方式1 —— 推荐(C99之后支持)
struct Student s1 = {
    .name = "张三",
    .age = 20,
    .score = 88.5f
};

// 方式2 —— 顺序初始化(最原始)
struct Student s2 = {"李四", 21, 92.5f};

// 方式3 —— 部分初始化(其余为0)
struct Student s3 = {"王五"};

// 方式4 —— 清零(最常用初始化方式)
struct Student s4 = {0};

5. 结构体指针最常用写法(非常非常重要!)

struct Student
{
    char name[64];
    int age;
} stu;

// 方式1(最常用、最推荐)
struct Student *p = &stu;

// 两种等价写法(一定要非常熟练)
(*p).age = 18;          // 方式A
p->age = 18;            // 方式B  ← 99%的情况下都用这个!

6. 位域(Bit Field) —— 省内存神器(面试中高级常考)

struct Flags
{
    unsigned int flag1 : 1;   // 只占1bit
    unsigned int flag2 : 1;
    unsigned int flag3 : 2;   // 占2bit
    unsigned int flag4 : 4;
    // 总共占用 1+1+2+4 = 8 bit = 1 byte
};

struct Flags f = {0};
f.flag1 = 1;
f.flag3 = 3;

位域限制(一定要记住):

  • 不能取地址(&操作)
  • 不能是double、float、long long
  • 不能跨越存储单元(不同编译器可能不同)

7. 结构体与typedef的黄金搭配(最最常用写法)

// 写法1(最推荐!几乎所有现代C代码都这么写)
typedef struct
{
    char name[64];
    int age;
    float score;
} Student;

// 使用方式
Student s1;               // 直接用类型名,不用再写struct
Student *p = &s1;
p->age = 18;

// 写法2(也很常见)
typedef struct Student Student;

// 写法3(最原始,但现在很少用了)
struct Student
{
    ...
} typedef Student;

8. 结构体经典面试/笔试高频题型汇总

  1. 求sizeof(结构体) (内存对齐最重要)
  2. 成员偏移量怎么求?(offsetof宏)
  3. 结构体里面嵌套结构体怎么对齐?
  4. 位域怎么用?位域的内存布局是怎样的?
  5. 结构体作为函数参数是传值还是传指针?(99.9%用指针)
  6. 结构体数组、结构体指针数组、指针数组的区别?
  7. 结构体和共用体(union)在内存占用上的本质区别?

最后送你一句最重要的话:

“只要涉及到结构体,就一定要想到内存对齐”

只要写到结构体指针,就一定要用 -> 而不是 .

只要定义结构体类型,强烈建议搭配 typedef 使用

需要我帮你把哪几种写法、哪几道经典题再展开讲得更细一点?
或者想看某一类题目(比如内存对齐)的10道经典例题?直接告诉我~

文章已创建 4391

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部