当前位置: 首页 > news >正文

C语言基础知识-学习笔记

1.IDE开发工具:

1.1.常用开发工具很多,本次学习用的是Visual Studio,官网直接下载,免费使用,下载安装方便。

2.C语言概述

2.1.概述:

通俗来说就是一种机器语言,人与机器交互的工具。C语言通过编译,生成机器可以读懂的语言,通过执行相应的命令,从而实现我们想要的功能。

2.2.C语言程序结构

程序是由一个或者多个函数组成

必须以main() 函数为入口,执行向对应的代码指令。程序开头可以引入C语言自带的包,或者开发者自己编写好的包,引入后可以直接调用包里的方法。

函数包含:声明(函数名称、返回类型、参数形式)和函数体(执行内容)

2.3计算机基础:

1.位、字节、字长的定义

1位 :1bit ,1kb=1024bit (2的10次方 1024)

1字节 = 8bit。

cpu一次并行处理的位数:字长。

比如64位计算机,就是一次可以并行处理16位

2.西文编码:从ASCII码到字符显示

ASCII码:就是用二进制编码表示字符(7位或者8位),实现了字符以二进制形式存在到计算机内存中。字符编码解决了字符的存储问题,但是没有解决字符的显示问题,需要有字符的字型数据。

字形数据:点阵数据(8*8点阵)、矢量数据(笔画)

3.汉字字符编码

西文字符,用一个字节进行编码。

国标码:GB23120-80 1980年颁发 (4位16进制数表示) 6千多汉字

字形码:点阵数据(16*16点阵)、矢量数据(笔画)

现在计算都是用

GBK编码:对GB23120-80进行了补充,2001年颁布了GB18030 可收录2.6万个汉字。

4.计算机的硬件系统

组成:输入设备(键盘、鼠标 等)+处理设备/单片机(存储器、运算器、控制器)+显示设备(显示器、打印机、投影仪等)

存储器:内存储器(ROM只读存储器 RAM随机存储器)、外存储器

RAM:SRAM高速缓存、 DRAM内存条

外存储器:硬盘、U盘、光盘、软盘

显卡:数据信号转换成模拟信号。

3.C语言-数据和C

3.1.示例程序:

#include <stdio.h> //引入包 //主函数 返回int类型 参数类型 为空 void butler(void); void getyour_val(void); int main(void) { int num; //定义变量 参数类型 变量名称 num = 1; //变量赋值 printf("调用了stdio包里的打印函数 %d \n" , num); //打印函数 %d 为占位符,用后面参数代替 getyour_val(); return 0; //函数返回值 } void getyour_val() { float weigth; float val_n; printf("请按kg为单位,输入您的体重 \n"); scanf_s("%f", &weigth); //接收输入参数 val_n = weigth * 980.4*1000; printf("与你体重相同黄金价格是:%f 元\n", val_n); }

执行效果:

3.2.变量与常量

程序要完成各项任务,就需要使用数据:即承载信息的数字和字符。

常量:有些数据类型使用之前就设定好了,整个程序执行过程中没有变化。

变量:有些数据类型在程序执行期间可能会被赋值或者改变,这些称为变量。

3.3.数据类型和关键字

关键字说明典型占用
基本数据类型int整型通常 4 字节
char字符型(本质是小整数)1 字节
float单精度浮点型4 字节
double双精度浮点型8 字节
类型修饰符
不单独使用
short短整型(如 short int)
long长整型(如 long int、long double)
signed有符号(默认即是有符号)
unsigned无符号(只表示非负数)
常见组合示例:unsigned int、long long、unsigned char。
构造类型(派生类型)struct结构体,成员内存连续分配
union联合体/共用体,成员共享同一段内存
enum枚举类型,定义命名的整数常量集合
类型定义与特殊类型typedef为已有类型起别名(如 typedef unsigned int uint;)
void空类型,用于无返回值函数、无参数列表、void* 通用指针
C99 / C11 标准新增的类型_BoolC99布尔类型(需包含 <stdbool.h> 后可用 bool)
_ComplexC99复数类型
_ImaginaryC99虚数类型
_AtomicC11原子类型(用于并发编程)

3.3.1 位、字节、字

位:最小存储单位:0/1

字节:1个字节为8位 256种情况

字:设计计算机给定的自然存储单位。

8位计算机:一次可以处理8个位的数据,也叫8字计算机。

64位计算机:一次可以处理64个位的数据,也叫64字计算机。

3.3.2整数和浮点数

整数:直接按二进制存储

浮点数:转成科学计数法,以二进制的形式,分开存在符号位、小数位和指数位

ps:浮点数因为存储方式的原因,在运算过程中可能会损失部分精度。

3.4.基本数据类型

【代码示例】

#include <stdio.h> #include <stdint.h> int main(void) { // 标准类型大小(32位MCU上) printf("char: %lu 字节\n", sizeof(char)); // 1 printf("short: %lu 字节\n", sizeof(short)); // 2 printf("int: %lu 字节\n", sizeof(int)); // 4 printf("long: %lu 字节\n", sizeof(long)); // 4 printf("long long: %lu 字节\n", sizeof(long long));// 8 printf("float: %lu 字节\n", sizeof(float)); // 4 printf("double: %lu 字节\n", sizeof(double)); // 8 // 嵌入式首选:固定宽度类型(stdint.h) int8_t a = -128; // 精确 8位 有符号 uint8_t b = 0xFF; // 精确 8位 无符号 int16_t c = 1000; // 精确 16位 uint32_t d = 0xDEADBEEF;// 精确 32位 return 0; }

【代码讲解】

嵌入式开发中,int 在不同平台可能不同(8位单片机是16位,32位MCU是32位)。使用 <stdint.h> 中的固定宽度类型(int8_t/uint16_t等)可以消除移植隐患。

sizeof 是编译期运算符,返回类型或变量的字节数。常用来计算数组长度、结构体大小等。

char 在任何平台都是 1 字节,是 C 语言最小的寻址单位。

3.5.有符号和无符号混用陷阱

#include <stdio.h> #include <stdint.h> int main(void) { int32_t a = -1; uint32_t b = 2; // 危险!有符号会被隐式转换为无符号 if (a < b) { printf("-1 < 2\n"); } else { printf("-1 >= 2 (无符号比较结果!)\n"); } // 输出:-1 >= 2 (无符号比较结果!) // 因为 -1 转为 uint32_t 变成 0xFFFFFFFF // 正确写法:统一类型 if (a < (int32_t)b) { printf("正确:-1 < 2\n"); } return 0; }

【代码讲解】

当 有符号 和 无符号 类型在同一个表达式中比较或运算时,有符号数会被隐式转换为无符号数

-1 转为 uint32_t 后变成 0xFFFFFFFF(4294967295),远大于 2,导致逻辑错误。

这是嵌入式开发中极常见的 bug 来源,尤其在数组索引、循环条件中。

因此尽量用相同类型进行比较,或者无符号转成有符号进行比较

3.5.1.for循环的简单使用

#include <stdio.h> #include <stdint.h> int main(void) { int i = 10; //uint8_t i = 10; for ( i ; i >= 0; i--) { printf("输出数据i:%d \n", i); } return 0; }

正常通过for循环,依次输出 10,9......0

如果i设置成uint8_t类型,再循环到0之后 会把-1被隐式转换为无符号数,下溢变成255,永远都是>=0,程序会进入死循环。

3.6.整数溢出与环绕

int main(void) { uint8_t i = 255; i = i+1; printf("输出上溢数据uint8_t 255+1:%d \n", i); //输出为 0 uint8_t ix = 0; ix = ix - 1; //没有下溢,因为-1不能赋值给无符号变量 printf("输出下溢数据uint8_t 0-1:%d \n", ix); //输出为 255 int8_t i2 = 127; i2 = i2 + 1; printf("输出上溢数据int8_t 127+1:%d \n", i2); //输出为 -128 int8_t i3 = -128; i3 = i3 - 1; printf("输出下溢数据int8_t -128-1:%d \n", i3); //输出为 127 // 嵌入式中的实际应用:计数器环绕 uint32_t timer = 0xFFFFFFFF; timer++; // 变成 0,定时器常用此特性 printf("输出上溢数据uint32_t timer :%d \n", timer); //输出为 0 return 0; }

4.指针与地址操作

指针(Pointer)​ 本质上是一个变量,但它存储的不是普通数据,而是另一个变量的内存地址

指针是 C 语言的灵魂,也是嵌入式开发的核心。寄存器访问、DMA 配置、内存映射、回调函数都离不开指针。

4.1.指针基础与取地址

int main(void) { uint32_t var = 120; uint32_t *p = &var; // p 指向 var 的地址 printf("var 的值: %d\n", var); printf("var 的地址: %p\n", (void*)&var); printf("p 指向的值: %d\n", *p); *p = 12; // 通过指针修改值 printf("修改后 var: %d\n", var); // 指针运算 uint16_t arr[4] = { 0, 1, 2, 3 }; uint16_t *q = arr; q++; // 指针存数组,指向的是arr[0]地址,p++后 就指向 arr[1] printf("arr[1] = %d\n", *q); printf("arr[1]地址 = %p\n", &*q); return 0; }

1.指针定义: 类型 *指针名; 例: uint16_t *q

2.指针赋值: *指针名 = 内容(常量、地址、变量、数组 等);

例:*p=12;*p = &var;*p = var

3.获取指针:*指针名 或者 指针名,例:*p(指针存的内容)或p(内容存的地址)

4.2.指针与数组的关系

数组名 buf 在表达式中会退化为指向首元素的指针;

数组赋值给指针后(p= buf; // 不用 &,buf 本身就是地址),两者可以看成是同一个数组指针。

我们可以获取数组内容,也可以或者到每个数组成员的地址。

#include <stdio.h> #include <stdint.h> #include <stdlib.h> int main(void) { uint16_t buf[11] = { 0,1,2,3,4,5,6,7,8,9,10}; // 数组名在大多数语境下退化为指针 uint16_t *p; p = buf; // 不用 &,buf 本身就是地址 printf("sizeof(buf) %zu \n", sizeof(buf)); //22 数组所有元素的字节 printf("sizeof(p) %zu \n", sizeof(p)); //8 指针字节 64位系统 uint16_t指针 8字节,32位系统则是4 printf("sizeof(p) %zu \n", sizeof(p[0])); //2 元素字节 int n = sizeof(buf) / sizeof(buf[0]); printf("arr_len(buf) %d \n", n); // 11 元素个数 // 以下三种方式完全等价 printf("%d\n", buf[3]); // 下标访问 printf("%d\n", *(buf + 3)); // 指针偏移+解引用 printf("%d\n", 3[buf]); // 等价写法(少用) p[5] = 99; // 通过指针下标赋值 printf("buf[7] %d\n", buf[7]); printf("通过指针下标赋值后的结果 buf[5] %d\n", buf[5]); //获取地址 printf("p %p\n", p); printf("&p[0] %p\n", &p[0]); printf("buf %p\n", buf); printf("&buf[0] %p\n", &buf[0]); return 0; }

5.结构体与联合体


6.位操作与位域


7.内存管理


8.函数与函数指针


9.预处理与宏


10.volatile 与 const


11.中断与回调函数


12.寄存器映射与硬件访问


13.编译与链接


14.常见嵌入式陷阱与最佳实践

http://www.cnnetsun.cn/news/4106250.html

相关文章:

  • 基于大模型与持续学习的人形机器人叠衣系统实战解析
  • 光度立体成像全栈拆解 | 多视角光影法向量求解+梯度积分重建,助力漫反射工件微划痕凹坑褶皱高速高精度2.5D缺陷检测
  • 深挖C语言:深入理解指针(2)
  • 线性可调双路输出电源:原理、设计与噪声抑制全解析
  • 当“让用户满意”变成“让用户更不满意”:AI防御误触发的根源与破解之道
  • OptiCommPy模拟光马赫-曾德尔调制器
  • CAD绘图效率提升:从练习图29拆解系统绘图流程与高效命令组合
  • snpe-VGG案例(uv环境-全流程 教程)
  • 实测通勤15分钟出片全流程,不用电脑不用大内存手机
  • 基于树莓派的智能交互装置:从硬件搭建到AI对话引擎实现
  • 企业信息管理:从“罗生门”到一致性回应的体系构建
  • OPOR-Bench: Evaluating Large Language Models on Online Public Opinion Report Generation
  • AE字体动画核心技巧:从基础动画器到批量预设应用
  • 2026毕业论文AI生成工具打分:6款谁更靠谱
  • 百度网盘Mac版免费提速完整方案:1个开源插件解锁SVIP高速下载(附避坑指南)
  • 使用CD4051实现8路模拟信号复用:硬件设计与Arduino编程指南
  • 用Python打造智能双模机械键盘:从硬件焊接、CircuitPython编程到高级功能实现
  • 基于世界模型与持续学习的自适应机器人系统构建指南
  • meteor-collection-hooks教程:remove钩子实现级联删除的完整指南
  • 基于RP2040与MicroPython的Pi Day灯光项目:从硬件选型到交互实现
  • 基于UNIHIKER K10的财富雨互动游戏开发:触摸、声音与姿态控制
  • OneNote 页面编号终极指南:用 OneMore 三步搭出专业级文档结构
  • G-Helper 上手指南:用一款开源轻量工具,让华硕笔记本性能、静音与续航兼得
  • Autojs基础-Shell命令(shell)
  • 在ARM和国产芯片上部署容器化项目总是失败?这份跨架构实战指南帮你一次过关
  • STM32CubeIDE与RT-Spark开发板:从零实现LED闪烁的完整指南
  • 基于MAX7219与MD_Parola库实现多块8x8 LED点阵屏文字滚动
  • CentOS7 tar包安装mysql8.0
  • Habitat-Sim 从零到实战:具身AI 3D仿真器的完整部署与应用指南
  • 免费开源AI修图工具IOPaint:三步抹掉照片中的路人、水印和文字