C语言入门——嵌入式学习笔记
在学习嵌入式系统时,C语言的重要性不可忽视。作为嵌入式开发的主流语言,C语言以其高效的执行速度、直接访问硬件的能力以及良好的可移植性,成为处理资源受限的嵌入式设备(如微控制器和传感器)的理想选择。许多实时操作系统(RTOS)和底层驱动都基于C语言构建,掌握C语言能帮助学习者深入理解内存管理、指针操作和硬件交互等核心概念,从而为实际嵌入式项目(如物联网设备或工业控制系统)打下坚实基础。
目录
一、前言
在学习嵌入式系统时,C语言的重要性不可忽视。作为嵌入式开发的主流语言,C语言以其高效的执行速度、直接访问硬件的能力以及良好的可移植性,成为处理资源受限的嵌入式设备(如微控制器和传感器)的理想选择。许多实时操作系统(RTOS)和底层驱动都基于C语言构建,掌握C语言能帮助学习者深入理解内存管理、指针操作和硬件交互等核心概念,从而为实际嵌入式项目(如物联网设备或工业控制系统)打下坚实基础。
二、C语言的基本结构
1.第一个C语言代码:
#include <stdio.h> int main(void) { printf("hello world!\n"); return 0; }说明:
必须三合一:
声明:告诉编译器函数定义和变量定义在哪里
定义:具体的函数或变量定义实现的地方
调用:跳到定义的地方,执行具体的函数或变量
流程:
遇到调用的函数,编译器先检查一下之前有没有这个声明,有的话直接跳到那个函数的定义实现的地方执行。
详解:
练习:
在C语言中,“<>”引用的头文件和双引号“”头文件的区别:
答:
头文件一般出现在程序前面,主要用于声明接口、共享代码结构和常量,避免重复定义所以叫头文件。
双引号头文件:先在工程文件里找,再从环境里面找头文件,适用于项目本地头文件
“<>”号头文件:从环境里找头文件,适用于标准库、第三方库的头文件
2.头文件
在C语言中,任何符号(包括变量和函数)的使用,都是需要提前声明的
如果程序用到了系统库函数,那么就需要包含相应的系统文件进行声明
#include <stdio.h> // 告诉编译器在.h文件中(声明)有这么一个符号,编译器回去其相应的.c文件里去找其实现(定义)比如我们的第一个C语言程序中:
打印“hello world"的printf函数包含在库函数stdio.h里面,
所以我们就需要提前声明头文件#include<stdio.h>
声明:
概念:对源文件外定义的某个符号进行描述的过程,称为声明
作用:经过声明的符号,编译器才能正确识别和编译,否则编译器不认识,无法判定语法错误
符号:变量、函数等
示例:
// 声明一个变量符号n extern int n; // 声明一个函数符号funA extern int func(void); // 注意:前面的extern的关键字是可以不写的,但是我建议初学者一定要加
3.主函数
- 主函数是必须有的,每一个C语言程序都有main函数,哪怕是空的。
- 主函数的名字是固定的,叫 main ,这个函数名不可被挪作他用。
- 主函数是程序的入口,也就是程序开始运行的地方。
- 主函数分解如下:
// int: 返回值类型,代表主函数最终的执行结果是一个整型数据 // main: main是函数名,这个名字不能变 // void: 是函数参数列表,可以省略,表示空的意思,就是没有参数的意思 int main(void) { ........ } // 使用花括号括起来的是函数体(里面的语句和动作,只能作用在这个函数体里面)在Liunx环境下,主函数main根据程序最终是否需要接收外部命令行参数,实际上有两个版本:
// 不接收外部命令行参数的版本 (ubuntu终端的你敲的那些命令) int main(void) { ... } // 接收外部命令行参数的版本 int main(int argc, char const *argv[]) { ... }
4.printf函数
C语言被称为面向过程的模块化语言,而所谓的模块指的是一个个功能明确,各司其职的封装函数,如同一块块积木,被合理有机地拼搭起来,形成复杂、健壮的程序。
在这之中,系统标准C语言提供了非常多的"模块",printf函数就是其中之一,它的功能就是:向终端输出一段指定格式的数据。
(1)格式:
int printf(const char *format, ...); // 这个函数参数的意思是,字符串fomat里面有多少个格式,后面就有多少个参数,以逗号分隔
(2)图解:
(3)常见的格式控制符号
一、基础的格式控制符 %d // 十进制数,decimalism %o // 八进制数,octonary %x // 十六进制数,hexadecimal %c // 字符,character %s // 字符串,character string %f // 浮点型,float %p // 地址、指针:pointer代码:
#include <stdio.h> int main(int argc, char const *argv[]) { int num = 100; // 定义了一个整形类型的叫num的变量,并给其赋值为100这个数 char buf[128] = "narenqiezaidenghuolanshanchu"; // 定义了一个char型数组,该数组的空间内存为128个字节大小,里面存放了这些个字符 float f1 = 3.1415; // 定义了一个float型的叫f1的变量,并给其赋值为3.14 // 1、没有格式控制符的函数 printf("hello world!\n"); // 2、打印十进制数 printf("十进制数 == %d\n", num); // 要求打印num这个变量的时候,使用十进制表示 // 3、打印八进制数 printf("八进制数 == %o\n", num); // 要求打印num这个变量的时候,使用八进制表示 // 4、打印十六进制数 printf("十六进制数 == %x\n", num); // 要求打印num这个变量的时候,使用十六进制表示 // 5、打印字符(本质上是一个整型数(1个字节)) printf("字符 == %c\n", num); // 要求打印num这个变量的时候,使用字符表示 /* 一开始计算机中没有固定的数据(0101 ....)来表示字符(abcdeef!@#$%^&*) 所以后面定了一个标准:ASCII表(这个表描述了相关的字符(128个字符),对应的数据就是(0-127)) */ // 6、打印字符串 printf("字符串 == %s\n", buf); // 要求打印buf这个变量的时候,使用字符串表示 /* 问题: 如果以字符串形式打印num的值,printf("字符串 == %s\n", num);,会出现一下问题 warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=] 原因: 类型不匹配 */ // 7、打印小数(浮点型) printf("小数(浮点型) == %f\n", f1); // 要求打印f1这个变量的时候,使用浮点型来表示 // 8、打印地址 printf("num == %p\n", &num); // &:取地址符号,意思是获取num这个变量的地址 /* printf("num == %p\n", num); 输出为:0x64(这个是值,不是地址,只不过以十六进制表示出来而已) printf("num == %p\n", &num); 输出为:0x7fff27e25ce8(这个是地址,以十六进制表示) */ return 0; }代码结果:
(4)常见的转义字符
说明:
转义字符通常前面有"\"符号
一、基本转义字符 \n - 换行符。将光标移动到下一行的开始位置。***** \t - 水平制表符。通常会将光标移动到下一个制表位。*** \\ - 反斜杠。用来表示实际的反斜杠字符。* \' - 单引号。用来表示实际的单引号字符。* \" - 双引号。用来表示实际的双引号字符。* \? - 问号。虽然问号本身不需要转义,但在某些情况下为了防止与三字母序列混淆,可能会用到。 \a - 警报声。发出警报声。 \b - 退格。将光标向后移动一个字符的位置。 \f - 换页。跳转到下一页的开始位置。 \r - 回车。将光标移动到当前行的开始位置,但不换行。*** \v - 垂直制表符。通常会将光标移动到下方的垂直制表位。 \ooo - 其中ooo是1到3位的八进制数 \xhh - 其中hh...是一个或多个十六进制数字。(\101 和 \x41 都代表大写字母 'A' 的ASCII码值65) 二、背景色、字体色显示转义字符 a、格式:\033[40-47;30-37m b、说明: 40/30: 黑色(背景色/字体色) 41/31: 红色 42/32: 绿色 43/33: 黄色 44/34: 蓝色 45/35: 紫色 46/36: 深绿色 47/37: 白色 c、使用: printf("\033[40;32m《学生信息管理系统》\n"); 三、显示效果转义字符 \033[0m // 关闭特效 \033[1m // 高亮效果 \033[4m // 下划线效果 \033[5m // 闪烁效果(只有ubuntu18.04系统及以上才具备这个效果) \033[7m // 反显(交换前景色和背景色) \033[8m // 消隐(文本不可见) 四、光标设置 \033[2J // 清除屏幕 \033[x;yH // 定位光标(x:横轴坐标, y:纵轴坐标) \033[yA // 上移光标(y是纵轴移动的位置) \033[yB // 下移光标 \033[xC // 右移光标(x是横轴移动的位置) \033[xD // 左移光标 \033[H // 复位光标 \033[?25l // 隐藏光标 \033[?25h // 显示光标 \033[u // 恢复光标位置 \033[s // 保存光标位置 \033[K // 清除从光标到行尾的内容
5.return语句
C语言中的关键字 return 的含义是结束一个函数,并返回某个数据(若有)。而具体到 main 函数中时,由于主函数 main 的结束同时也意味着整个程序的结束,因此在上述 Hello World 程序中 return 后整个程序就退出了。
int main(void) { ... ... // 一般而言,函数正常退出返回0,非正常退出返回非0 return 0; }注意:
main函数的返回值是给上一级进程的,因此理论上讲在当前的单进程程序中,main函数的返回值究竟是多少都无所谓,因为根本没有其它进程去使用这个返回值,除非在多进程程序中,进程间才需要使用main函数的返回值来传递信息。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐






所有评论(0)