找回密码
 立即注册
查看: 99|回复: 5

求c51结构体讲解视频

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:435
  • 最近打卡:2026-03-23 17:06:18

188

主题

251

回帖

467

积分

中级会员

积分
467
发表于 2026-3-9 19:14:55 | 显示全部楼层 |阅读模式
一直对c51结构体搞不明白,也从来没有用过,哪里可以看到详细的视频讲解?
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:841
  • 最近打卡:2026-03-23 07:51:55
已绑定手机

58

主题

2015

回帖

3627

积分

论坛元老

积分
3627
发表于 2026-3-9 20:01:37 | 显示全部楼层
何老师有C教程
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:645
  • 最近打卡:2026-03-23 15:27:18

33

主题

2912

回帖

6555

积分

论坛元老

积分
6555
发表于 2026-3-10 08:56:58 | 显示全部楼层
结构体看不明白 你不应该找一找C语言的教程么0.0
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:359
  • 最近打卡:2026-03-20 21:53:40

844

主题

1万

回帖

2万

积分

管理员

积分
22719
发表于 2026-3-10 09:28:13 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:253
  • 最近打卡:2026-03-23 08:44:19
已绑定手机

22

主题

627

回帖

2324

积分

金牌会员

积分
2324
发表于 2026-3-10 10:20:54 | 显示全部楼层
就是将多个数据打包到一起而已
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:838
  • 最近打卡:2026-03-23 06:19:26

12

主题

1328

回帖

7148

积分

论坛元老

积分
7148
发表于 2026-3-10 11:40:44 | 显示全部楼层

c51结构体讲解 一直对c51结构体搞不明白,哪里可以看到详细的讲解 在51单片机上使用的C语言(C89标准)中的结构体, 在C89标准下有什么特殊的限制或注意事项。 在51单片机上使用C语言(遵循C89/ANSI C标准),其结构体的核心语法与标准C一致,但有几个源自C89标准和51单片机自身架构的关键约束,是你特别需要留意的。不允许的 sbit, sfr 结构体, 位变量 bit 也不能有数组

在 51 单片机上用 C89 标准的 C 写结构体,语法本身跟标准 C 是一样的;你碰到的坑主要来自「8051 这个怪异硬件」和「C51 这类编译器的扩展与限制」,而不是 C89 本身。1

下面我按几点把关键约束理一下,也顺带给一些“正确写法 vs 不允许的写法”的例子。


1. C89 标准本身对 struct 的约束

在纯 C89 语义里,8051 特有的这些东西——sbit、sfr、bit 类型、内存空间关键字 data / xdata / code——通通是不存在的,它只认识普通的对象类型和地址。2

C89 对结构体的大致约束是:

  • 结构体成员必须是“完整类型”,不能是:
    • 未完成的 struct 自身(只能是指针指向不完整类型)。
    • 函数类型(只能是函数指针)。
  • 成员在内存中顺序排列,各成员按其对齐要求插空填充,不会自动重排。
  • 允许结构体嵌套结构体、允许结构体包含数组(数组元素是任何完整类型)。1

所以像下面这种,在纯 C89 语义上完全没问题:

struct Foo {
    int  a;
    char buf[^10];
    struct Foo *next;   /* 指针允许,不能是 struct Foo 本身 */
};

这些在 8051 上一般也语法上是允许的,问题是“它放在哪块内存、怎么对齐、指针怎么表示”才会出事。1


2. 8051 + C51 的内存模型对 struct 的影响

8051 有多个物理地址空间:DATA、IDATA、XDATA、CODE、SFR 等,各家编译器(Keil C51、RC51、SDCC 等)都用关键字把对象强制放入某个空间,比如:dataidataxdatacodesfrsbitbit2

关键点:

  • C89 里根本没有这些关键字,它们都是编译器扩展,所以“遵循 ANSI C/C89”只能理解为“在不使用这些扩展时语义一致”。2
  • 一旦你在结构体中出现这些扩展类型(sbit、sfr、bit)或空间限定语法,就超出了 C89 范围,完全由具体编译器拍脑袋决定是否支持。3

常见的做法是:

/* 普通 C89 风格的结构体,只包含标准类型 */
struct UartCfg {
    unsigned char baud_div;
    unsigned char mode;
    unsigned char ctrl;
};

然后再配合 8051 特有的 SFR/SBIT 定义去操作寄存器,而不是把 SFR 或 sbit 塞到 struct 里去。3


3. 为什么 sbit / sfr 不能放进结构体

以 Keil C51 为例:

  • sfr / sbit 是“特殊函数寄存器”和“位寻址寄存器”的声明修饰,本质上是“把变量绑死到绝对地址”。3
  • 编译器用特定的指令序列操作它们(mov P1, #immsetb P1.0,等等),而不是像普通变量那样在 RAM 里按偏移量访问。3

结构体成员访问的语义是:“以结构体基地址 + 偏移”的方式访问连续内存,所以它要求成员是“内存里的偏移量”,而不是“一个独立的绝对地址绑定对象”。1

因此:

/* 错误/不被支持的想法:拿 sfr / sbit 当 struct 成员 */
struct Port1Bits {
    sbit p1_0;
    sbit p1_1;
    sbit p1_2;
    /* ... */
};

这在很多 C51 编译器中是直接不允许的或者行为未定义,因为它无法把“结构体偏移”跟“绝对地址位”兼容起来。 正确做法通常是:4

/* 单独声明 sfr / sbit */
sfr  P1  = 0x90;
sbit P1_0 = P1 ^ 0;
sbit P1_1 = P1 ^ 1;
/* ... */

/* 如果要逻辑组合,自己写 inline 函数/宏,不用 struct 封装位 */
#define LED1   P1_0
#define BUTTON P1_1

所以你的总结“sbit、sfr 不能作为结构体成员”是对的:这不是 C89 的规定,而是 8051 C 编译器实现上的硬限制。3


4. bit 类型与 bit 数组 / bit 成员

Keil C51 有一个独有的 bit 类型,对应 8051 的 bit-addressable 区域(20h–2Fh 等)或单独的位变量。2

注意几点:

  1. bit 不是 ANSI C 类型,纯 C89 编译器根本不认。2
  2. 许多 8051 编译器不允许
    • bit 数组(bit flags[^8];);
    • 结构体成员为 bit 数组;
    • 某些情况下,结构体成员为 bit 本身。

常见限制的原因:

  • 真正的“位寻址单元”在硬件上是一堆离散的 bit 地址,不是连续的字节数组;用“偏移”抽象起来很难,而且会增加指令开销。1
  • 编译器一般只支持“单个 bit 变量” + “bit 的指针非常受限”这类简单模式。5

因此下面的写法在很多 C51 上会报错或行为未定义:

/* 常见禁止写法:bit 数组 */
bit flags[^8];          /* 通常不允许 */

/* struct 里放 bit 数组,基本一定不行 */
struct Foo {
    bit flags[^8];
};

比较安全的模式:

/* 用 unsigned char 做 bit-map,自行按位操作 */
struct Flags {
    unsigned char f0 : 1;
    unsigned char f1 : 1;
    unsigned char f2 : 1;
    unsigned char f3 : 1;
    unsigned char f4 : 1;
    unsigned char f5 : 1;
    unsigned char f6 : 1;
    unsigned char f7 : 1;
};

/* 或者统一用 uint8_t 做掩码 */
typedef unsigned char u8;

struct State {
    u8 flags;   /* flags 的每一位自行通过位运算读写 */
};

位段(bitfield)虽然是 C89 标准的一部分,但在 8051 C 编译器上经常有奇怪行为(对齐、跨字节打包、不可移植),Keil 自己也提醒“不要用它做精确硬件映射”。5


5. 几个在 51 上用 struct 的实战注意点

这些是你在 C51/SDCC 上会经常踩到的坑,很多看似和 C89 语法有关,实际上是 8051 工具有问题:

  1. 结构体所在内存空间要明确
    • 如果你用 xdatadata 等关键字修饰结构体变量,整个 struct 都会放到对应空间:
struct Foo {
    unsigned char a;
    unsigned char b;
};

xdata struct Foo g_foo;   /* 整个结构体在外部 RAM */
- 这会影响指针类型(`xdata struct Foo *` 与 `data struct Foo *` 不是一种指针),注意函数参数类型要匹配。[^1]
  1. 不要指望 struct 和硬件寄存器“一一对齐”
    • 很多新手习惯用 struct 做“寄存器表”映射,8051 上极不推荐。
    • 因为:
      • 寄存器分布在 SFR、bit-addressable RAM、XDATA 等多个空间;
      • 结构体要求连续内存,寄存器物理上不连续。3
  2. 尽量只在 struct 里放“普通 C 类型”
    • char / unsigned char / int / long / enum / 指针 / 数组 等都是安全的。
    • 把针对硬件的东西(sfr、sbit、bit、特殊宏)放在别的层次做封装,用函数/宏读写;struct 更多承载“软件层逻辑状态”。1
  3. 数组 + struct 没有特别的 C89 限制
    • 标准 C89 中,struct 里放数组完全 OK。
    • 如果你在 C51 里碰到“struct 里放数组报错”的情况,90% 是被 datacodexdata 这些关键字撞到了(例如你把成员名字写成 data,被当成关键字),而不是 C89 的问题。7

6. 总结成几句“记忆口诀”

结合你提到的那句:

不允许的 sbit, sfr 结构体, 位变量 bit 也不能有数组

可以整理成在 51 + C51 (C89) 环境下的实践规则:

  • 结构体的语法按 C89 思考;但成员类型只用标准 C 类型(整数、指针、数组、嵌套 struct/union)。1
  • sbit、sfr、bit 都是编译器扩展,不要塞进 struct / union;bit 类型也不要做数组,用字节做 bit-map 自己按位操作。2
  • 结构体变量如果要放特定内存(data/xdata/idata),在变量声明处加空间限定,不要在成员里玩花样。1
  • 如果要操作端口位、SFR 位,直接用 sfr+sbit 定义和宏/函数封装,而不是图省事做一个“寄存器 struct”。3

如果你愿意,可以把你现在正在写的某段 struct + sbit/sfr 相关代码贴一段,我可以帮你按“可移植 C89 struct + 8051 特有寄存器访问层”拆分重构一版。
9


  1. https://www.esacademy.com/en/library/technical-articles-and-documents/8051-programming/using-pointers-arrays-structures-and-unions-in-8051-c-compilers.html

  2. https://chipprogrammer.blogspot.com/2016/12/data-types-in-c.html

  3. https://www.keil.com/dd/docs/c51/cygnal/c8051f520.h

  4. https://community.arm.com/support-forums/f/keil-forum/15203/defining-bit-field-structure-to-use-sfr-p1

  5. https://community.arm.com/support-forums/f/keil-forum/34527/c51-functions-returning-bit-type---efficiency-and-opinions-for-or-against

  6. https://www.keil.com/support/index/c51.htm

  7. https://stackoverflow.com/questions/34697444/defining-struct-containing-array-in-c51-not-allowed

  8. https://community.arm.com/support-forums/f/keil-forum/35250/impact-of-using-bit-instead-of-sbit-for-sfr-while-declaring

  9. http://lsa.isep.ipp.pt/~aprender/pagina_lsa/aprender/manuais_cv/C51Primer.pdf

  10. http://cwcyrix.nsupdate.info/willem-eprom-stuff/cd-rom/dump/eprom-programmer-v3b/doc/e-book/c51 primer.pdf

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-23 23:09 , Processed in 0.114005 second(s), 63 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表