C结构体的几种定义形式 + typedef结合使用的好处

发布于:2025-08-06 ⋅ 阅读:(20) ⋅ 点赞:(0)

struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:

        struct tag 
        {
                    member-list
                    member-list
                    member-list  
                    ...

        } variable-list ;

tag 是结构体标签。

member-list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义。

variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。

在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。以下为实例:

 C 结构体 | 菜鸟教程(<----摘抄了一部分菜鸟的C教程,这里链接给一下)

一、基本的结构体定义 (不使用 typedef)

1. 声明了 结构体标签;不声明结构体变量。(方式1)

struct  结构体标签  {
    数据类型  成员1;
    数据类型  成员2;
    // ... 更多成员
};

这种是结构体最常用也是最基本的定义方式。

struct: 关键字,表示定义一个结构体。

结构体标签: 给这个结构体类型起的名字 (类似于盒子的名字)。 你以后可以靠这个标签来声明这个类型的变量。

{ ... }: 花括号里定义一个个“成员”(类似于盒子里的每一个积木)。每个成员都有自己的数据类型(比如 intfloatchar)和名称。

//使用举例:
struct Point 
{ 
        int x; 
        int y; 
}; 

// 声明一个Point类型的变量(创建了一个盒子) 
struct Point p1; //每次声明变量的时候,都需要加上 struct 关键字。
p1.x = 10; // 访问成员 
p1.y = 20; // 访问成员 

特点: 每次声明变量的时候,都需要加上 struct 关键字。

2. 声明了 结构体变量;不声明 结构体标签。(方式2)

struct {
  数据类型  成员1;
  数据类型  成员2;
  // ...
} 变量名;

这种方式 没有结构体标签,它直接定义一个匿名结构体的变量。 创建一个盒子,并给这个盒子装上东西,但是没有给盒子起名字。

//使用举例:
struct {
    int x;
    int y;
} p5; // 定义了一个匿名的结构体变量 p5

p5.x = 70;
p5.y = 80;

// 再次定义会报错,因为结构体“长相”不同
// struct {
//   int x;
//   int y;
// } p6;  // 错误!

特点: 只能在定义的时候创建变量。 无法再创建同类型的其他变量,因为没有结构体标签来指示类型。 通常很少使用。

 

3. 同时声明了 结构体变量 和 结构体标签。(方式3)

struct 结构体标签 
{ 
        数据类型 成员1; 
        数据类型 成员2; 
        // ... 更多成员 
}变量名;

解释: 同时定义了结构体标签P2和结构体变量S2。后续可以再通过结构体标签 P2,再定义S3,S4之类的结构体变量(struct P2 S3,S4;),可以理解其走了两步,第一步为:struct P2

{ int a; char b; double c; };  第二步为:struct P2 S2;

1. .h 文件中直接定义这种形式,在编译中不通过,这种形式同时完成了结构体声明和结构体定义,想象一下,如果你把 struct P2 S2; 放在一个 .h 文件里,并被多个 .c 文件 #include 了。 那么,每个包含这个 .h 文件的 .c 文件都会试图创建变量 S2。 这会导致 重复定义错误 (编译器会报错,因为同一个变量被多次定义了)。

2.可以放在某个.c文件中编译通过;

二、与 typedef联合使用

1.  使用 typedef 定义结构体 (带标签)(方式4)

typedef struct 结构体标签 {
    数据类型  成员1;
    数据类型  成员2;
    // ...
} 新的类型名;


/*

typedef 
struct 结构体标签 {
    数据类型  成员1;
    数据类型  成员2;
    // ...
} 
别名;

*/

typedef: 关键字,用于给一个数据类型(包括结构体)起个别名。

新的类型名: 你给这个结构体类型新起的名字 (类似于给盒子起个外号)。 以后可以用这个新的名字来声明变量,而不需要写 struct 了。

typedef struct  Point  {  // 这个结构体叫 Point,并且起了一个"别名" MyPoint
    int x;
    int y;
} MyPoint;

// 声明一个Point类型的变量(创建了一个盒子)
MyPoint p2;  // 不需要写 "struct" 了!
p2.x = 30;
p2.y = 40;

特点:以后声明变量时,可以直接使用新起的类型名。更简洁,更方便。 推荐使用 typedef 来定义结构体。

2. 使用 typedef 定义匿名结构体 (无标签)(方式5)

typedef struct {
    数据类型  成员1;
    数据类型  成员2;
    // ...
}  新的类型名;

这种定义方式 没有结构体标签。 这样定义的结构体只能通过 typedef 赋的别名来使用。

//使用举例:
typedef struct {  // 没有 "结构体标签"
    int x;
    int y;
} MyPoint;  // 定义结构体的时候同时定义了别名

MyPoint p3;
p3.x = 50;
p3.y = 60;

// 错误,因为没有定义结构体名称
// struct { int x; int y; } p4;  // 错误!

    特点: 只能使用 typedef 定义的别名来声明变量。 因为没有结构体标签,所以无法再用 struct { ... } 变量名; 这种方式定义变量。

    3.在结构体定义时就进行初始化 (配合 typedef 与否均可)

    解释: 在定义结构体变量的同时,给它的成员赋值。

    3.1使用 typedef

    typedef struct Point {
        int x;
        int y;
    } MyPoint;
    
    MyPoint p1 = {100, 200};  // 直接初始化
    

    3.2不使用 typedef

    struct Point {
        int x;
        int y;
    };
    
    struct Point p2 = {300, 400};
    

    总结:
    • 推荐: 使用 typedef 结合结构体标签。 这样既可以给结构体起别名,又方便以后阅读和维护代码。

    • 一般避免: 直接定义匿名结构体变量(方式2)。 因为你很难重复使用这个类型。

    • 匿名结构体: 适合在定义后立即使用,并且不希望再定义同类型结构体的情况。 比较少见。


    网站公告

    今日签到

    点亮在社区的每一天
    去签到