C 语言--sizeof与typedef

本文介绍了C语言中sizeof操作符的应用及typedef的作用。详细解释了如何使用typedef简化复杂类型的声明,并展示了如何结合malloc和sizeof初始化链表结构。

sizeof 与 typedef

sizeof作为C语言中求取类型所占字节数的宏,经常配合malloc等使用。
typedef则是用来表明,类型别名。

typedef struct ListElmt_ {
    void *data;
    struct ListElmt_ *next;
}ListElmt;

通过使用typedef,可以直接用ListElmt来代替struct ListElmt结构体类型。

typedef struct List_ {
    int size;
    ListElmt *head;
    ListElmt *tail;
    void (*destroy)(void *data);
    int (*match)(const void *key1, const void *key2);
 } List;

在使用链表时,可以使用malloc函数

List *list = (List *)malloc(sizeof(List));
list_init(list);

在链表中,每个链表元素包含的数据都是数据的地址,这样,由于对应不同的类型,如何销毁元素就需要自定义List中的destroy函数,如果需要排序比较,也需要同时定义match函数。

```c MNTRLINK_CFG_T cfg = {0}; memset(&cfg, -1, sizeof(cfg)); ``` 这段代码的含义执行效果如下: --- ### ✅ 代码作用分析 #### 第一步:`MNTRLINK_CFG_T cfg = {0};` - 将结构体 `cfg` 的所有成员**初始化为 0**。 - 这是 C 语言中标准、安全、推荐的清零方式。 - 无论结构体有多少字段,只要用 `{0}` 初始化,未显式列出的字段都会被自动设为 0。 > ✔️ 结果:整个 `cfg` 被清零(每个字节为 0x00)。 #### 第二步:`memset(&cfg, -1, sizeof(cfg));` - 使用 `memset` 函数将 `cfg` 占据的内存块 **每一个字节都设置为 `0xFF`**(即 -1 的无符号字节表示)。 - `memset` 是按字节填充的函数: ```c void *memset(void *s, int c, size_t n); ``` 其中 `c` 虽然是 `int` 类型,但实际只取低 8 位(即 `c & 0xFF`),所以: - `-1` → 补码表示是全 1(即 `0xFFFFFFFF`) - 取低 8 位就是 `0xFF` - 所以每个字节都被填成 `0xFF` > 🔥 最终结果:结构体所有字节变为 `0xFF`,即每个整型成员变成 `-1`(在补码机器上) --- ### 🔄 实际等效过程 ```c MNTRLINK_CFG_T cfg = {0}; // 所有字段 = 0 memset(&cfg, -1, sizeof(cfg)); // 再把所有字节改为 0xFF → 所有 int 成员变成 -1 ``` 相当于: ```c MNTRLINK_CFG_T cfg; for (size_t i = 0; i < sizeof(cfg); i++) { ((char*)&cfg)[i] = 0xFF; } ``` 最终效果 ≈ 所有整型字段为 `-1`,指针字段为无效地址(如 `0xFFFFFFFF`),padding 区域也为 `0xFF`。 --- ### ⚠️ 潜在风险问题 虽然这在某些嵌入式或驱动开发中用于“标记无效配置”,但存在以下问题: | 风险 | 说明 | |------|------| | ❌ 破坏 padding 字节 | 结构体可能有对齐填充字节,`memset` 会修改这些区域,虽然不影响正确性,但不必要 | | ❌ 指针成员被设为 `0xFFFFFFFF` | 如果结构体包含指针,解引用会导致段错误 | | ❌ 不可移植 | 假设整数用补码(现代系统基本都支持),但理论上不是强制要求 | | ❌ 浪费操作 | 先 `{0}` 再 `memset(-1)` 相当于白做一次清零 | --- ### ✅ 更优写法建议 如果你想让所有字段为 `-1`,直接跳过 `{0}` 初始化: ```c MNTRLINK_CFG_T cfg; memset(&cfg, -1, sizeof(cfg)); ``` 或者使用指定初始化器(C99+)逐个赋值: ```c MNTRLINK_CFG_T cfg = { .enable = -1, .group = -1, .priority = -1, // 显式设置每个字段 }; ``` > 推荐后者用于可读性安全性。 --- ### 示例验证代码 ```c #include <stdio.h> #include <string.h> typedef struct { int a; int b; int c; } MNTRLINK_CFG_T; int main() { MNTRLINK_CFG_T cfg = {0}; printf("初始化后: a=%d, b=%d, c=%d\n", cfg.a, cfg.b, cfg.c); // 0 0 0 memset(&cfg, -1, sizeof(cfg)); printf("memset(-1)后: a=%d, b=%d, c=%d\n", cfg.a, cfg.b, cfg.c); // -1 -1 -1 return 0; } ``` 输出: ``` 初始化后: a=0, b=0, c=0 memset(-1)后: a=-1, b=-1, c=-1 ``` --- ### 总结 | 写法 | 是否推荐 | 说明 | |------|----------|------| | `= {0}; memset(..., -1, ...)` | ❌ 不推荐 | 多余操作,先清零再覆盖 | | `memset(&cfg, -1, sizeof(cfg))` | ⚠️ 谨慎使用 | 快速设所有字段为 -1,但危险 | | 指定初始化 `.a = -1, .b = -1` | ✅ 推荐 | 安全、清晰、可维护 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值