嵌入式 C 语言入门:循环结构学习笔记 —— 从语法到实用技巧

前言

大家好,这里是 Hello_Embed。在前文中,我们学习了分支结构(if/switch),让代码能根据条件 "选择执行";而循环结构则能让代码 "重复执行"------ 比如实现 LED 持续闪烁、反复读取传感器数据等。本文将详细讲解 C 语言中三种循环结构(while、do-while、for)的语法、差异及嵌入式场景的应用,同时介绍 break 和 continue 对循环的控制,帮助你掌握从基础语法到硬件控制的落地技巧。

🔄 while 循环:先判断后执行
语法与执行逻辑

while 循环的核心是 "先判断条件,再决定是否执行循环体",语法如下:

c 复制代码
while(条件表达式){
	// 循环体:条件为真时执行
}

触发逻辑

  1. 判断条件表达式是否为真(非 0);
  2. 若为真,执行循环体,执行完毕后回到步骤 1 再次判断;
  3. 若为假,直接跳过 while 语句,执行后续代码。
实例:计算 1-3 的和

通过简单代码理解 while 的执行过程:

c 复制代码
#include <stdio.h>
int main()
{
    int sum = 0, i = 1;
    while (i <= 3)  // 条件:i不大于3
    {
        sum = sum + i;  // 累加i的值
        i++;            // 更新i(避免死循环)
    }
    printf("The sum of first 3 natural numbers is %d", sum);
    return 0;
}

运行结果如图:

整个过程中,i 从 1 开始,每次循环后自增,直到 i=4 时条件不成立,循环结束。

🔄 do-while 循环:先执行后判断
语法与执行逻辑

do-while 循环与 while 的核心区别是 "先执行一次循环体,再判断条件",语法如下:

c 复制代码
do{
	// 循环体:至少执行一次
}while(条件表达式);  // 注意末尾的分号

触发逻辑

  1. 先执行一次循环体;
  2. 判断条件表达式是否为真;
  3. 若为真,回到步骤 1 再次执行循环体;若为假,结束循环。
实例:同样计算 1-3 的和

对 while 的例子稍作修改,用 do-while 实现:

c 复制代码
sum = 0;
i = 1;
do{
    sum = sum + i;
    i++;
} while(i <= 3);  // 执行后判断
printf("\nThe sum of first 3 natural numbers is %d", sum);

运行结果如图输出仍为6

当循环条件一开始就成立时,while 和 do-while 的结果一致。

🆚 while 与 do while 的关键差异

通过 "计算字符串长度" 的例子对比两者的区别:

c 复制代码
#include <stdio.h>
int main()
{
    // 测试1:非空字符串
    char *str = "1234567890";
    int cnt = 0;
    // while循环:先判断是否到结束符'\0'
    while(str[cnt] != '\0') { cnt++; }
    printf("The length of the string is %d\n", cnt);
    
    cnt = 0;
    // do while循环:先执行一次,再判断
    do { cnt++; } while(str[cnt] != '\0');
    printf("The length of the string is %d\n", cnt);

    // 测试2:空字符串
    char *str1 = "";  // 仅含结束符'\0'
    cnt = 0;
    while(str1[cnt] != '\0') { cnt++; }  // 条件一开始为假,不执行
    printf("The length of the string is %d\n", cnt);
    
    cnt = 0;
    do { cnt++; } while(str1[cnt] != '\0');  // 先执行一次,cnt变为1
    printf("The length of the string is %d\n", cnt);
    return 0;
}

注意:在这里我们定义了指针char *str = "1234567890"而非char类型数组是因为如下几点优势:

  • 效率更高:无需复制字符串,直接引用只读内存区的原始数据(1234567890)。
  • 适合只读场景:如果仅需读取字符串内容(如计算长度、遍历字符),使用指针更简洁。
  • 非空字符串时,两者结果相同(均为 10);
  • 空字符串时,while 返回 0(一次也不执行),do-while 返回 1(至少执行一次)。
    结论:do-while 适合 "至少执行一次" 的场景(如用户输入验证),while 适合 "可能一次都不执行" 的场景。
🔄 for 循环:结构化的循环控制
语法与执行逻辑

for 循环将 "初始化、条件判断、更新" 整合在一行,结构更清晰,语法如下:

c 复制代码
for(初始表达式; 条件表达式; 更新表达式){
	// 循环体
}

执行顺序 (这里引用韦东山视频教学中的框图,我觉得很形象)

  1. 执行一次初始表达式(如i = 0);
  2. 判断条件表达式(如i < 10):
    • 若为真,执行循环体,然后执行更新表达式(如i++),回到步骤 2;
    • 若为假,结束循环。
灵活用法:死循环

for 循环的三个表达式均可省略,for(;;)等价于while(1),表示条件永远为真,形成死循环:

c 复制代码
for(;;){
	// 循环体:无限重复执行
}

在嵌入式中,死循环常用于主程序逻辑,例如实现 LED 闪烁(这里仅展示部分代码):

c 复制代码
volatile unsigned int *p = (volatile unsigned int *)0x40021414;  // ODR地址
int i;
while(1)  // 等价于for(;;)
{
	*p &= ~(1 << 9);  // 点亮LED
	for(i = 0; i < 100000000; i++);  // 延时
	*p |= (1 << 9);   // 熄灭LED
	for(i = 0; i < 100000000; i++);  // 延时
}
🔍 循环与分支的结合:筛选字符串中的数字

通过 "从字符串中提取数字" 的例子,看循环与 if 的结合应用:

c 复制代码
#include <stdio.h>
int main()
{
    int i = 0;
    char *p = "2idiosbac901h8caioj0912";  // 含数字和字母的字符串
    while (p[i] != '\0')  // 循环遍历字符串,直到结束符
    {
        // 利用ASCII码连续性:'0'-'9'的ASCII码为48-57
        if (p[i] >= '0' && p[i] <= '9') {
            printf("%c", p[i]);  // 打印数字字符
        }
        i++;  // 移动到下一个字符
    }
    return 0;
}

运行结果如图,成功提取出所有数字。

关于代码:这里我们巧妙地利用了数字"0-9"ASCII码的连续性。我们知道0-9的ASCII码依次为:48-57,当我们要判断p[i]的ASCII码值刚好在这个范围则说明它必定为0-9,这也是我们筛选数字的基础。

🎮 循环的控制:break 与 continue
两者的区别
  • break:直接跳出当前循环,不再执行后续循环;
  • continue :跳过本次循环的剩余部分,直接进入下一次循环。
    通过代码演示:
c 复制代码
#include <stdio.h>

// break演示:触发后终止循环
void demo_break() {
    printf("----- break演示 -----\n");
    for (int i = 0; i < 3; i++) {
        if (i == 1) {
            printf("  触发break,跳出循环\n");
            break;
        }
        printf("  循环第%d次\n", i+1);
    }
}

// continue演示:触发后跳过本次
void demo_continue() {
    printf("\n----- continue演示 -----\n");
    for (int i = 0; i < 3; i++) {
        if (i == 1) {
            printf("  触发continue,跳过本次\n");
            continue;
        }
        printf("  循环第%d次\n", i+1);
    }
}

int main() {
    demo_break();
    demo_continue();
    return 0;
}

运行结果如图,差异一目了然。

实例:查找字符串中的字符

用 break 优化查找效率,找到目标后立即终止循环:

c 复制代码
#include <stdio.h>
int main()
{
    int i;
    int found = 0;
    char *str = "fhue45icnan";  // 目标:查找'5'
    for(i = 0; str[i]; i++) {  // str[i]非'\0'时继续
        if(str[i] == '5') {
            found = 1;
            break;  // 找到后跳出循环
        }
    }
    if(found == 1)
        printf("Found, location is %d\n", i);  // 输出位置
    else
        printf("Not Found\n");
    return 0;
}

运行结果如图,成功定位到 '5' 的位置(索引 5):

结尾

本文讲解了 while、do-while、for 三种循环的用法:while 适合简单条件判断,do-while 适合至少执行一次的场景,for 适合结构化控制;break 和 continue 则让循环更灵活。在嵌入式开发中,循环是实现周期性任务(如数据采集、状态监测)的核心,结合分支结构能构建复杂的硬件控制逻辑。

下一篇,我们将学习函数与参数的传递,看看如何将重复代码封装成函数,让程序更模块化。Hello_Embed 与你继续深入 C 语言的嵌入式应用,下篇见!

相关推荐
-Xie-1 小时前
JVM学习日记(十三)Day13
jvm·学习
重生之我是Java开发战士2 小时前
【C语言】内存函数与数据在内存中的存储
c语言·开发语言·算法
sakoba2 小时前
Docker学习其二(容器卷,Docker网络,Compose)
运维·网络·学习·docker·容器·基础
im_AMBER3 小时前
学习日志25 python
开发语言·python·学习
慕y2743 小时前
Java学习第九十六部分——Eureka
java·学习·eureka
南棱笑笑生3 小时前
20250802让飞凌OK3576-C开发板在飞凌的Android14下【rk3576_u选项】适配NXP的WIFIBT模块88W8987A的蓝牙
c语言·开发语言
tngyrn4 小时前
机试备考笔记 2/31
笔记
tt5555555555554 小时前
电力系统分析学习笔记(二)- 标幺值计算与变压器建模
笔记·学习·电路
厄罗萌多4 小时前
OpenCV学习 day3
opencv·学习·计算机视觉