嵌入式基础知识复习(C语言)

前瞻

7.28 嵌入式产品特点、开发环境、计算机组成、Linux终端初识

1、嵌入式 产品。特点 :低功耗、根据用户需求定制。硬件 :arm处理器。软件:Linux操作系统

arm架构 :精简指令集、低功耗(移动/嵌入式)。 x86架构:复杂指令集、高功耗。(PC机/服务器)

Linux操作系统 :开源可裁剪。 windows操作系统:非开源不可裁剪。

2、**Linux发行版之一:ubantu。**即对Linux内核进行封装和功能完善,形成了一个方便用户交互的完整操作系统。(详细见附录一)

3、**C语言:**面向过程的编程语言。(详细介绍见附录二)

4、**计算机基本组成:**cpu、ram(内存)。

cpu负责控制与运算、存储器负责数据中转。

存储器分类:ram(随机存储器,掉电数据丢失)、rom(只读存储器)

计算机存储最小单元:字节(byte)。1byte = 8bit。每个存储单元对应一个内存地址。

(详细见附录三)

5、Linux终端:

1)linux@ubantu:@前面是用户名,@后面是主机名
2)相对路径:相对当前路径来说的路径(不包含根目录)。绝对路径:从根路径开始描述(包含根目录)。
3)~/是家目录,扩展开是/home/linux。
4)绝对路径的第一个/就是是linux根目录,后面/是分隔符。
5) 命令组成:command [-option] [argument]
命令符 选项 参数

6)permission denied 表示权限不足,要在命令前加sudo,输入用户密码。
7)不要随意点击终端、vim界面的窗口关闭(×),容易造成文件内容未保存丢失。

7.29 GPU(显卡)与cpu(处理器)、大小端存储、缓冲区

1、计算机的GPU参与浮点数运算、cpu整型运算,所以这两种数据类型不能混淆。

2、如果vim编辑器有高亮配置,关键词一般会高亮。(关键词见附录5)

3、在ram中,数据存储方式包括:

大端存储:低地址存储高位。例如51单片机。

小端存储:低地址存储低位(一个地址对应一个字节,8bit)。例如x86、arm。

复制代码
0x12345678
小端存储                    大端存储
地址    数据                地址    数据
2000     78                2000     12      
2001     56                2001     34
2002     34                2002     56
2003     12                2003     78

4、C语言代码写完会保存到rom,当运行时会从rom提取代码到ram运行。

5、gcc编译器只作类型检查,所以代码只要类型匹配,编译不会报错,但运行时可能因为其他原因导致程序崩了。

6、缓冲区:当一个高速设备遇到低速设备,高速设备会等低速设备,造成性能损失,这时候就需要缓冲区,例如多字符输入时,键盘敲入的字符先进入缓冲区,是一个队列数据结构(FIFO先进先出模式),按回车后CPU就会来处理数据,当数据正确,CPU就会取走数据,数据错误,数据就不会离开缓冲区。

7.30 C语言函数编写原则

1、编写C语言源程序时要保持高内聚低耦合的原则。即不同函数间内容不要重合,单一函数内部功能单一,具体解释见附录七。

前瞻结束

7.28 C语言数据类型、数据存储格式、进制转化

1、C语言数据类型:

1)常量:程序运行过程值不变的量。整型常量、字符常量

变量:程序运行过程值改变的量。变量可以看成一段内存空间,程序运行结束空间销毁。

2)常量分类

整型常量:十进制8、八进制01000、十六进制0x8。

浮点型常量:1.23、0.123e1 (常量小数默认是双精度,详细见附录四)。

字符常量(ascll码):'a'、'\n'、'1'、'!',实际上亦可以看成整型,因为每一个字符都可以转化为对应整型数字。

宏常量:#define N 10;

3)变量分类:

整型变量:(无符号)短整型 (unsigned)short:2字节

(无符号)整型 (unsigned)int 4字节

(无符号)长整型 (unsigned)long 8字节

浮点型变量 :单精度浮点型 float 4字节

双精度浮点型 double 8字节

字符变量: (unsigned)char 1字节

字符常量用单引号括起来,当单引号里面有多个字符,默认值是最后一个字符。

2、数据存储格式

**整数存储格式:**补码存储。

正数补码是它本身,负数补码是原码取反加一(最高位符号位不变)。

当存储时数字超过类型范围会发生溢出,存储错误的结果(如unsigned char 256,实际存储0)。

单精度浮点数存储格式:符号位1位,阶码8位,尾数23位。计算如下:

x = (-1)^s × (1.M) × 2^(E-偏移值),其中,s是符号位,M是尾数(不包括隐含的1),E是阶码,偏移值对于32位浮点数是127,对于64位浮点数是1023。

3、进制转化

十进制转二进制:整数部分:除二取余法。小数部分:乘二取整法。

二进制转十进制:按位乘2的n次方再加起来。

二进制转八进制:每三位二进制转一位八进制。

二进制转十六进制:没四位二进制转一位十六进制

7.29 C语言标识符、#预处理、程序入口、转义字符、运算符、数据类型转化、标准输入输出

1、C语言标识符(变量名、函数名、标签等):

1)由字母、数字、下划线组成

2)首字符必须是字母或下划线

3)标识符命名不能跟关键词重复

2、C语言带#都是预处理指令,在编译前先进行预处理,即文本替换,例如头文件包含会直接替换成头文件内容、宏定义直接文本替换、条件编译直接替换为为真的代码部分。

3、C语言程序必须有一个main函数作为程序入口,且只能有一个。

4、C语言转义字符:一些不可见字符,虽然看似两个字符,实际表示一个字符,仍为char类型。

复制代码
\n    换行 
\t    水平制表(八格制表)    例:abc\tcd,输出为abc     cd,c前共有八格(abc加上5个空格);
\b    退格(左箭头)   例:Hello\b123输出hell123,Hello\b\b123输出Hel123;
\r    回车(光标移到本行开头) 如hello\r123输出123lo
\f    换页
\\    输出一个斜杠
\'    输出单引号
\"    输出双引号
\ooo    三个八进制数,输出Ascll表对应字符
\xhh    两个十六进制数,输出Ascll表对应字符

5、C语言运算符(见附录六):

优先级排序:自高到低,相同优先级按结合方向排序(只有单目运算符、三目运算符、赋值运算符是自右向左结合)

1、 初等运算符:() [] -> .

2、 单目运算符: ! ~ ++ -- (类型) * & sizeof

3、算数运算符:* / %

4、算术运算符:+ -

5、移位运算符:<< >>

6、关系运算符:< <= > >=

7、关系运算符:== !=

8、位与:&

9、位异或:^

10、位或:|

11、逻辑与: &&

12、逻辑或:||

13、条件运算符(唯一三目):? :

14、赋值运算符:= += -= *= /= %= >>= <<= &= ^= |=

15、逗号运算符:,

**注意:求余运算%:**操作数必须是整型,结果正负由左操作数决定,右操作数不能位0。

**++i 跟 i++:**二者的i变量值实际都已经加一,但是整个表达式前者已经加一,后者没有加。前置加加效率高些。

**逗号表达式:**最后一个表达式作为整个表达式的值。

**赋值运算:**把double变量值存到int变量,会造成小数部分截断,反之没影响。

short变量值存到int中,会根据short值的正负进行符号位扩充,负数会在空的高字节补1,正数补0。反之int值存到short会高字节截断。

把有符号整型存到无符号中,内存中的值不变,因为存储空间相同。可以看出,赋值运算就是内存拷贝

6、C语言的变量定义时赋值称为初始化,定义后赋值称为赋初值,前者效率高些。

7、C语言的数据类型转化

隐式类型转换:编译时自动转化,按下表进行。例如:表达式'a' + 10,两个操作数分别是字符型和整型,根据下标,字符型自动转化为整型,所以表达式的结果是整型。易错题:

unsigned int a = 5; a = a+(-2); a的值应该是7。

显示类型转化:利用运算符:(类型)

8、C语言的临时变量(匿名变量):运算过程临时产生的值,必须为右值。例如表达式的值就是临时变量,计算完就销毁。

9、C语言的const关键字 :定义变量时前面加上这个关键词,表示该变量只读类型,后面不能改变其值。

10、C语言程序分为三种结构:顺序结构、选择结构、循环结构

一个C程序包含若干源程序文件,每个源程序文件包括预处理指令、数据声明和若干函数,每个函数包括函数首部和函数体,函数体包括数据声明和执行部分。

11、代码中输入输出是相对于计算机说的,从计算机向外部输出数据称输出(如打印机、显示器),输入设备指向计算机输入数据(如鼠标、键盘、扫描仪)。C语言本身不包含输入输出函数,输入输出来自标准输入输出库函数stdio.h。这种方式使得C语言简单高效。

12、C库的输入输出函数:

单字符输入输出: char putchar(int ) 只能输出一个字符
int getchar() 输入一个字符,返回字符整型值

getchar是从缓冲区拿走字符。当想要清理缓冲区字符时,可以用这个while(getchar != '\n'){}取出缓冲区字符。

多字符输入输出:

int printf (const char*format,...) 第一个参数是字符串,字符串里可以放占位符,占位符由函数后面的参数代替。 函数返回值是整型,大小为实际字符个数。

注意: const char*表示字符串。

int scanf(const char*,...) 通过键盘向计算机输入数据。第一个参数是字符串,后面的参数放地址。当输入多个字符时,间隔符可以是空格 tab或者换行符。返回值是个整型,测试得到大小为正确输入的个数。

注意:后面的参数如果不是地址,会出现段错误,导致程序运行崩溃segmentation fault(core dumped)。
scanf()函数中的字符串里除了占位符不要加其他东西,否则输入时还要加上这些东西,最后不要加\n。
输入函数占位符必须与输入数据类型一致。因为地址没有隐式必转。

浮点数输入不能指定精度、宽度。

输入遇到空格、tab、换行、到达指定宽度、非法输入就会结束

复制代码
格式符
%hd      短整型
%010d    宽度为10,前面补零,只能补零或者空格。
%#o      会输出0...
%#x      会输出0x...
%e、%E   科学计数法表示,(如1230.0,表示为1.230000e+3)
%f、%F   十进制表示法,默认保留6位小数。输出函数单精度也按照双精度处理(隐式转换)
%m.nf    m是宽度,n是小数位数,宽度不够默认右对齐补空格,m前加- 表示左边补空格
%g,G     两种浮点数表示方法(浮点数、科学计数法)哪个短用哪个表示。
%c       输出字符
%s       输出字符串
%p       打印地址,十六进制
%%       输出%。
%lld     输出long long整型
%lu      无符号长整型。
7.30 循环结构、选择结构、数组及排序查找问题

1、C语言选择结构(条件分支结构):

1)if else结构

if(表达式) {语句}:只有表达式逻辑值为1才执行语句。

if(表达式){语句一} else {语句二}:表达式逻辑值为1执行语句一,否则执行语句二

if(表达式一){语句一} else if(表达式二){语句二} else{语句三}:表达式一成立执行语句一,表达式二成立执行语句二,否则执行语句三。(三个表达式应满足互斥关系)

2)switch结构

switch(表达式)

{

case 常量表达式1:语句一;break;

case 常量表达式2:语句二;break;

case 常量表达式3:语句三;break;

default:语句四

}

通过表达式与常量表达式等值比较,值为一就执行后面对应语句,break跳出花括号。(表达式需要是整型或者整型相兼容的类型,case后必须是常量表达式)

2、选择结构判断会用到关系运算符、逻辑运算符等,

1)关系运算符:<= , < , >= , > , == , !=,前四个优先级高一些;

2)关系运算符加操作数就是关系表达式,关系表达式的值是逻辑值(整型,非0即1);

3)逻辑运算符:与&&、或||、非!(!优先级最高,&&优先级比||高);

4)逻辑表达式:逻辑运算符加操作数就是逻辑表达式。(逻辑表达式中按照从左到右执行,在与表达式,只要左值为0,整个表达式值为零,不进行后面表达式的计算,在或表达式中,只要左表达式为1,整个表达式的值就为1,不进行后面的表达式计算

3、条件运算符:

语句一?语句二 :语句三 语句一值为真执行语句二,否则执行语句三。

4、C语言循环结构:

1)goto循环:给一个语句命名,然后goto 标识符,就可以无条件跳转到标识符处执行后面的语句。例:

label:

printf("bbb");

goto label;

2)while循环:例:

while(1 == a)

{

printf("k");

}

当a=1时输出k。

3)do while循环:例:

do

{

printf("s");

}while(1 == a);

先执行一次循环体,再进行判定语句,符合要求就继续执行循环体。

4)for循环:例:

for(a = 1; a <= 4; ++a)

{

printf("s");

}

先执行a = 1;当a < 4时,输出s,然后执行a++,再判断a<4是否成立,成立则输出s,再执行a++,再判断,如此循环。

5、跳出循环语句:

1)break语句:执行后直接跳出所在层的循环。

2)continue语句:执行后结束所在循环的本轮循环,直接执行下轮循环。

**6、循环语句三要素:**循环变量初始化,循环条件语句,使循环趋于结束的语句。

7、数组: 类型 标识符[数字] 数组即一段连续的存储空间。

8、数组相关注意点:

1)数组只有在定义时初始化可以整体赋值,之后赋值只能一个个成员赋值

2)当在定义时初始化,可以省略成员个数。

3)数组成员下标从0开始

4)void不能定义数组

5)定义数组时的[]是类型说明符,之后是方括号运算符

6)数组在内存中存储元素具有连续性、有序性、单一性。

7)数组定义初始化如果花括号元素个数不足时会自动在后面补零。

8)数组大小为元素个数乘元素类型大小。

9)引用数组元素时要防止数组越界访问(下标不能超了)

10)数组名就是首元素地址

9、实现数组的元素遍历、排序、查找(下面介绍核心思想,具体实现程序见附录八)

1)数组元素遍历

直接按照下标一个个成员访问

2)数组元素排序

**逆序:**把第一个跟最后一个成员换位、然后第二个跟倒数第二个换,,,直到下标为元素个数/2的位置即可。

升序:

**1、选择排序:**从第一个元素开始,依次把该元素跟后面所以元素比大小,如果该元素大于后面的元素,就换值(完成所有比较就会把最小的值放当前位置),接着继续处理下一个,直到处理完倒数第二个元素即可。

**2、冒泡排序:**从第一个元素开始,相邻元素两两比较,如果前者大于后者就换值,直到倒数第二个元素(完成所有比较就把最大的值放到最后);接着处理下一个,直到处理完倒数第二个元素即可。

**3、插入排序:**从第二个元素开始,跟前面的数比较,看看它比哪个数大,比哪个数小,就把该数放在那两个数中间(这样就把从第一个元素到该元素的顺序先排好了);然后处理下一个,直到最后一个元素。

数字查找:

**遍历查找:**从第一个数开始,一一比较,直到发现哪个等于要找的数即可。

**二分查找法:**先对数组排序,假设为升序,先把要找的数跟中间的数比较,大于中数就在左边找,小于中数就在右边找(这样就缩短了查找区间);然后在新区间继续处理,直到处理完最后一个数即可。

ubantu快捷键、终端命令、vim编辑器命令

复制代码
//ubantu常用快捷键、终端命令、vim编辑器命令

一、Linux终端命令:
7.28:
ls                列出当前目录下文件及目录
ls -a             额外列出隐藏内容。 .是目录本身,..是上一层目录,带点文件是隐藏文件。
ls -l             列出当前目录下文件,同时显示文件详细信息(权限、创建时间、大小等);
ls --help         获取命令使用方法
pwd               打印当前路径
cd                回到家目录。
cd ..             退回上一层目录
touch 文件名      创建文件
mkdir 目录名      创建文件夹
rm 文件名         删除文件 
rm 文件夹 -r      删除文件夹
cp 文件 目录      文件拷贝至指定目录 
cp 文件夹 目录 -r 文件夹拷贝 
mv 文件 目录      移动文件
vi/vim 文件名     编辑文件
gcc 文件名(main.c)        c程序编译,生成a.out可执行程序
gcc 文件名 -o 目标名        编译生成指定目标名
./a.out                    可执行程序运行
7.29:
whatis 函数名/系统调用/命令         查看函数简短描述,可以知道在哪个章节描述
man 章节号 函数名/系统调用/命令      查看详细介绍
gcc 文件 -lm      编译时链接数学库


二、vim编辑器命令:
7.28
    刚进入默认命令模式,输入i进入编辑模式(INSERT),按ESC回到命令模式(NORMAL).
    保存退出:  :w保存   :q退出文件   :q!强制退出   :wq保存退出
    复制粘贴:命令模式下,移动光标到要操作的行:       
                    yy        复制1行
                    数字 yy    复制n行(包含当前行)
                    p         粘贴(以光标下1行为粘贴的第1行)
                    dd        剪切1行
                    数字 dd    剪切n行
    
    O    在光标下一格开空行进入编辑模式

三、ubantu快捷键:
7.28:
ctrl alt t    开启终端
ctrl shift +  终端字体放大
ctrl -        终端字体减小
tab           文件名自动补全
ctrl+alt+fn+f2    回到图形交互界面(默认开机界面)      
ctrl+alt+fn+f3    进入文字交互界面(可用于帧缓冲相关程序运行)
7.29:
ctrl shift t      打开另一个终端标签页
alt 数字           多标签页时页面切换
7.30
ctrl 空格         显示或隐藏输入法提示框
ctrl c            结束程序运行

附录一 ubantu与Linux内核

你的笔记基本正确,但表述可以更严谨。以下是综合搜索结果后的修正与补充说明:


Linux发行版与Ubuntu的关系

  1. 核心概念

    • Linux内核:由Linus Torvalds维护的操作系统核心,负责管理硬件资源(CPU、内存、设备驱动等)。
    • 发行版(Distribution):在内核基础上集成图形界面、软件包管理工具、应用程序等,形成完整的操作系统。
    • Ubuntu:是基于Debian的Linux发行版之一,由Canonical公司维护,以用户友好性和稳定性著称。
  2. 你的笔记修正

    • 原句:"对Linux内核进行封装,形成方便用户交互的版本"
    • 更准确表述 : Ubuntu是基于Linux内核的完整操作系统发行版,不仅封装内核,还集成了桌面环境(如GNOME)、软件包管理器(APT/Snap)、系统工具和社区支持,提供开箱即用的用户体验。
  3. 补充说明

    • 封装内容 :除内核外,还包括:
      • 桌面环境(如Ubuntu默认的GNOME)
      • 软件仓库(通过APT管理数千个开源软件包)
      • 系统工具(如防火墙、虚拟化支持)
      • 定制优化(如Ubuntu对Debian软件包的兼容性调整)
    • 交互设计:Ubuntu特别注重桌面用户的易用性,如图形化安装界面、Unity/GNOME桌面环境等。

Ubuntu与其他发行版的区别

特性 Ubuntu 其他发行版(如Fedora、CentOS)
基础 基于Debian,但软件包不完全兼容 Fedora基于RHEL,CentOS是RHEL的社区版
更新周期 每6个月发布新版本,LTS版支持5-10年 Fedora更新更快,RHEL/CentOS更注重稳定性
目标用户 个人桌面、开发者、云计算 Fedora面向技术爱好者,RHEL面向企业

总结与建议

  1. 笔记修正建议
    • 明确Ubuntu是"基于Linux内核的发行版",而非单纯"封装内核",强调其完整操作系统属性。
    • 补充Ubuntu的衍生版本(如Kubuntu、Xubuntu)和特色功能(如Snap包管理)。
  2. 扩展学习
    • Linux内核与发行版的关系类似"引擎与整车",内核提供基础能力,发行版决定用户体验。
    • 其他主流发行版包括Debian(Ubuntu上游)、Red Hat(企业级)、Arch Linux(极简主义)等。

如需更详细的技术对比,可参考Ubuntu官方文档或Linux内核开发资料。

附录二 C语言详细介绍

C语言作为计算机科学领域最具影响力的编程语言之一,自1972年诞生以来,一直是系统编程和底层开发的首选工具。本文将全面介绍C语言的发展历程、语言特点、标准演进以及广泛的应用领域。

一、C语言的历史与发展

C语言的起源可以追溯到1960年代的ALGOL 60语言,经过多个阶段的演变才形成今天我们熟知的C语言。

  1. 前身语言

    • ALGOL 60(1960年):面向问题的高级语言,但离硬件较远
    • CPL语言(1963年):剑桥大学在ALGOL 60基础上开发,更接近硬件但过于复杂
    • BCPL语言(1967年):Martin Richards简化CPL而来
    • B语言(1970年):Ken Thompson在BCPL基础上进一步简化,用于编写第一个UNIX操作系统
  2. C语言的诞生

    • 1972年,贝尔实验室的Dennis Ritchie在B语言基础上设计出C语言(取BCPL的第二个字母)
    • 1973年,C语言主体完成,并用它重写了UNIX操作系统(90%以上代码)
    • 1978年,AT&T贝尔实验室正式发表C语言,同时Kernighan和Ritchie合著《The C Programming Language》(简称K&R)
  3. 标准化进程

    • K&R C:1978-1989年间事实上的标准
    • ANSI C(C89):1989年美国国家标准学会制定,1990年被ISO采纳为ISO C(C90)
    • C99:1999年ISO发布,增加新特性
    • C11:2011年发布,支持汉字函数名和标识符
    • C18:2018年发布,主要是对C11的修正
    • C23:最新的C语言标准(2023年发布)

二、C语言的核心特点

C语言之所以能经久不衰,得益于其独特的设计理念和语言特性:

  1. 高效性与低级控制

    • 直接访问内存物理地址,进行位一级操作
    • 代码效率高,通常只比汇编语言低10%-20%
    • 不需要运行环境支持,编译后可直接运行
  2. 结构化与模块化

    • 层次清晰,便于按模块化方式组织程序
    • 易于调试和维护
    • 丰富的运算符和数据类型,便于实现复杂数据结构
  3. 可移植性强

    • 标准规格写的程序可在多种平台编译运行
    • 从嵌入式处理器到超级计算机都支持
    • 与特定硬件架构解耦
  4. 兼具高级与低级语言特性

    • 具有高级语言的抽象能力
    • 保留低级语言的硬件操作能力
    • 既适合系统软件开发,也适合应用软件开发
  5. 丰富的表达能力

    • 处理能力极强,可处理各类复杂问题
    • 绘图能力强,适合图形和动画开发
    • 支持多重编程范式(过程式、数据抽象等)

三、C语言的版本与编译器

  1. 主要版本

    • Microsoft C(MS C)
    • Borland Turbo C
    • AT&T C
    • GNU C(GCC)
  2. 现代常用编译器

    • GCC:GNU组织开发的开源免费编译器,支持多平台
    • Clang:基于LLVM的开源编译器,BSD协议
    • Visual C++:微软开发的Windows平台编译器
    • MinGW:Windows下的GCC移植版
    • Xcode:macOS上的开发环境,使用Clang
  3. 集成开发环境(IDE)

    • Windows:Visual Studio、Dev-C++、Code::Blocks
    • Linux:Eclipse CDT、KDevelop
    • 跨平台:CLion、VS Code(配合插件)

四、C语言的应用领域

C语言因其独特的优势,在计算机科学的多个领域都有广泛应用:

  1. 系统软件开发

    • 操作系统内核(UNIX、Linux、Windows)
    • 编译器(如GCC)、解释器
    • 设备驱动程序
    • 文件系统和存储管理
  2. 嵌入式系统

    • 单片机开发(裸机或RTOS)
    • 智能家居设备(空调、洗衣机控制器)
    • 汽车电子(ECU、BCU)
    • 医疗设备(监护仪、血糖仪)
  3. 高性能计算

    • 游戏引擎开发(Unity、Unreal)
    • 图形渲染和3D建模
    • 科学计算和数值分析
    • 信号处理(DSP)
  4. 网络与安全

    • 网络协议栈实现(TCP/IP)
    • Web服务器(Apache)
    • 加密算法和安全系统
    • 防火墙和入侵检测
  5. 数据库系统

    • MySQL
    • SQLite
    • PostgreSQL
    • Oracle和SQL Server的核心组件
  6. 工具链开发

    • 开发其他编程语言(Python、PHP等的解释器)
    • 构建系统和版本控制工具
    • 性能分析工具
  7. 多媒体处理

    • 音视频编解码(FFmpeg)
    • 图像处理(OpenCV)
    • 语音识别和合成

五、C语言的职业方向

掌握C语言可开启多种职业路径:

  1. 系统软件工程师:开发操作系统、编译器、工具链等系统软件
  2. 嵌入式系统工程师:设计嵌入式软件,应用于智能设备、汽车电子等领域
  3. 游戏引擎开发工程师:开发高性能游戏引擎和图形渲染系统
  4. 网络安全工程师:开发安全系统和加密算法,保护系统安全
  5. 数据库开发工程师:设计和优化数据库管理系统
  6. 物联网(IoT)开发工程师:开发智能设备和物联网解决方案
  7. 自动化测试工程师:开发底层测试框架和工具

六、C语言的影响与未来

  1. 对后续语言的影响

    • 直接催生了C++、Objective-C、C#等语言
    • 影响了Java、JavaScript、Python等语言的语法设计
    • 成为许多新语言的学习参考
  2. 在现代开发中的地位

    • 仍然是系统编程和性能敏感领域的首选
    • 在物联网和边缘计算时代获得新的应用场景
    • 作为计算机科学教育的基石语言
  3. 未来展望

    • 随着C23标准的发布,语言持续现代化
    • 在安全性和并发支持方面不断改进
    • 仍将是底层开发和系统编程的核心工具

七、学习C语言的建议

  1. 从基础开始:掌握数据类型、控制结构、函数等基本概念
  2. 深入理解指针:这是C语言最强大也最容易出错的部分
  3. 实践项目驱动:通过实际项目(如小型操作系统、游戏等)巩固知识
  4. 阅读优秀代码:学习Linux内核等开源项目的代码风格和设计
  5. 关注现代特性:了解C11、C17和C23引入的新特性

C语言作为一门接近50年历史的语言,依然活跃在技术前沿,其设计理念和哲学影响了几代程序员。无论是想深入理解计算机系统,还是从事底层开发工作,C语言都是不可或缺的核心技能。

附录三 计算机基本组成

你的笔记基本正确,但部分表述可以更严谨,以下是补充和修正后的版本,结合了搜索结果中的权威信息:


计算机基本组成

  1. CPU(中央处理器)

    • 功能
      • 控制:作为计算机的"指挥中心",通过控制器(CU)从内存取指令、译码并生成控制信号。
      • 运算:通过算术逻辑单元(ALU)执行算术(如加减乘除)和逻辑运算(如与、或、非)。
    • 组成
      • 运算器(ALU) + 控制器(CU) = CPU核心。
      • 寄存器:高速暂存指令和数据(如程序计数器PC、指令寄存器IR)。
      • 缓存(Cache):分L1/L2/L3三级,缓解CPU与内存速度差异。
  2. RAM(随机存储器)

    • 功能:临时存储CPU正在处理的程序和数据,断电后丢失(易失性)。
    • 分类
      • DRAM:动态RAM,需刷新(如内存条),成本低但速度较慢。
      • SRAM:静态RAM,无需刷新(如CPU缓存),速度快但成本高。

存储器分类与特性

类型 特性 用途
RAM - 可读写,速度快 - 易失性(断电数据丢失) 临时存储运行中的程序和数据
ROM - 通常只读,写入需特殊操作(如固件升级) - 非易失性(断电保留数据) 存储BIOS、嵌入式系统固件

:ROM演进类型包括PROM(一次性写入)、EPROM(紫外线擦除)、EEPROM(电擦除)和闪存(如SSD)。


存储单元与寻址

  1. 最小单元
    • 字节(Byte) = 8 比特(bit),是数据存储的基本单位。
    • 内存地址:每个字节对应唯一地址,CPU通过地址访问数据。
  2. 扩展概念
    • 字(Word):CPU一次处理的数据长度(如32位系统为4字节)。
    • 存储字长:存储单元中二进制代码的位数(如64位系统的字长为64bit)。

修正建议

  1. CPU部分
    • 补充控制器(CU)和运算器(ALU)的协同关系。
    • 增加寄存器组的作用(如PC、IR)。
  2. 存储器分类
    • 明确ROM的"只读"是历史名称,现代ROM(如EEPROM)支持有限写入。
  3. 存储单元
    • 区分"字节"与"字"的概念,避免混淆。

冯·诺依曼体系结构

计算机硬件五大核心组件:控制器运算器 (合为CPU)、存储器输入设备输出设备,通过总线连接。你的笔记中"存储器负责数据中转"可更精确为"存储器(内存+外存)存储程序和数据,供CPU直接访问"。

附录四 小数在C语言默认双精度类型。

在Linux系统中,浮点数常量的默认类型是双精度浮点数(double。这一规则不仅适用于Linux系统,也是C/C++语言标准的通用规范。以下是具体分析:


1. 语言标准与默认类型

  • C/C++标准规定 :根据C语言标准(如C18)和C++标准,未添加后缀的浮点数常量(如3.141.23e-5)默认类型为double

    • 若需指定为单精度(float),需显式添加后缀fF(如3.14f)。
    • 后缀lL表示long double(更高精度)。
  • 示例代码

    复制代码
    复制代码
    double a = 3.14;   // 默认double类型
    float b = 3.14f;   // 显式声明为float

2. 硬件与系统实现

  • IEEE 754标准 :Linux系统遵循IEEE 754浮点数标准,double类型通常占用64位(8字节),提供约15-17位有效数字,而float为32位(4字节),仅6-7位有效数字。
  • 性能与精度权衡 :现代处理器(如x86、ARM)对双精度运算有硬件优化,默认使用double可减少精度损失,但可能增加内存和计算开销。

3. 实际应用中的注意事项

  • 隐式转换风险 :将double常量赋给float变量时,编译器会自动截断,可能导致精度损失或警告。
  • 科学计算与嵌入式场景
    • 科学计算优先使用double以保证精度。
    • 嵌入式系统(如ARM Cortex-M)可能因资源限制选择float,需显式加后缀。

4. 为什么默认是double而非float

  • 历史与兼容性 :早期C语言设计时,double因其更高的精度和范围被选为默认类型,延续至今。
  • 避免意外截断 :默认double可减少因隐式转换导致的精度问题,尤其在复杂表达式中。

总结

在Linux系统中,浮点数常量默认类型为double,这是由语言标准、硬件支持及精度需求共同决定的。开发者应根据场景选择是否显式指定类型(如floatlong double),以平衡性能与精度需求。

附录五· C语言关键词介绍

以下是基于图片内容的 C语言关键词分类与功能解析,结合标准C11规范进行说明:


1. 数据类型相关关键字

关键字 作用
int 声明整型变量(通常占4字节,范围依赖平台)
char 声明字符型变量(1字节),也可用于小整数(-128~127)
float 单精度浮点数(4字节,约6-7位有效数字)
double 双精度浮点数(8字节,约15位有效数字)
short 短整型(通常2字节)
long 长整型(通常4或8字节),如long double扩展精度浮点
unsigned 修饰整型,表示无符号(如unsigned int范围0~4294967295)
signed 显式声明有符号类型(默认行为,通常省略)
void 表示无类型(用于函数返回值或指针泛型)

注意sizeof是运算符而非类型,用于计算对象/类型所占字节数(编译时确定)。


2. 流程控制关键字

类别 关键字 典型用法示例
条件分支 if/else if (x>0) { ... } else { ... }
多路选择 switch/case/default switch(n) { case 1: ...; break; default: ... }
循环 for/while/do for(int i=0; i<10; i++) / while(1) { ... }
跳转 break/continue/goto break;(跳出循环) / goto label;(慎用)

3. 存储类别与作用域

关键字 作用
auto 自动局部变量(C99后默认,极少显式使用)
register 建议编译器将变量存入寄存器(现代编译器自动优化,已弃用)
static 静态变量(局部变量持久化/全局变量文件内可见)或静态函数
extern 声明外部定义的变量/函数(跨文件引用)
volatile 防止编译器优化(用于硬件寄存器或多线程共享变量)
const 定义只读变量(实际可通过指针修改,但行为未定义)

4. 复合类型与自定义类型

关键字 作用
struct 定义结构体(成员内存连续,可能存在对齐填充)
union 定义联合体(所有成员共享同一内存空间)
enum 定义枚举类型(本质是整型常量)
typedef 类型别名(如typedef int MyInt;

5. 其他重要说明

  • 重复项 :图片中structwhile在第五列重复列出,实际为排版错误。
  • C标准差异
    • C99新增_Bool_Complex等,C11新增_Generic等,但图中未包含。
    • goto虽合法,但易破坏代码结构,应避免使用。
  • 常见误用
    • const int* p vs int* const p(前者指针可变,后者指向不可变)。
    • register在C++17中被移除,C语言中仍保留但无效。

完整关键词列表(按字母排序)

复制代码
auto break case char const continue default do double else enum extern 
float for goto if int long register return short signed sizeof static 
struct switch typedef union unsigned void volatile while

建议通过实际代码练习(如用switch实现状态机、union解析二进制数据)加深理解。

附录六 C语言运算符与优先级、结合方向

附录七 高内聚低耦合

你的笔记基本正确,但可以结合搜索结果中的专业定义和示例进一步细化和完善。以下是针对"高内聚低耦合"原则的详细解释与补充建议:


1. 高内聚(High Cohesion)

  • 定义 :内聚指一个模块(如函数)内部各元素(代码逻辑)围绕同一功能的紧密程度。高内聚要求函数功能单一且明确,所有代码均服务于同一目标。
  • 你的笔记 :提到"一个函数的功能尽量单一",这是正确的,但需补充内聚的层次划分:
    • 功能内聚(最佳):函数仅完成一个独立功能(如计算平方数或格式化输出)。
    • 反例
      • 偶然内聚:函数内代码无逻辑关联(如同时计算面积和打印欢迎语)。
      • 逻辑内聚 :函数通过参数选择不同功能(如print_info(type)同时处理学生和教师信息)。
  • 判断标准:删除函数中的某行代码后,若原功能无法完成,则内聚度高;否则可能存在冗余代码。

2. 低耦合(Low Coupling)

  • 定义 :耦合指模块间依赖关系的强度。低耦合要求函数间接口简单、依赖最少,避免相互影响。
  • 你的笔记 :提到"不同函数间的功能尽量不用重合",需更准确表述为**"减少函数间的直接依赖"**,具体表现为:
    • 数据耦合(推荐):通过参数传递简单数据(如值传递),函数独立性最强。
    • 反例
      • 外部耦合(最差):函数共享全局变量,导致调试困难(如多个函数修改同一全局变量)。
      • 特征耦合:通过指针或文件等共享复杂数据,增加依赖风险。
  • 实现技巧:使用接口(如回调函数)或封装(如面向对象设计)降低耦合。

3. 你的笔记改进建议

  1. 明确术语:区分"功能不重合"(避免重复代码)与"依赖关系简化"(低耦合的核心)。
  2. 补充示例
    • 高内聚示例:将"计算平方数"和"格式化输出"拆分为两个函数。
    • 低耦合示例:用参数传递替代全局变量。
  3. 强调设计阶段:高内聚低耦合需在编码前规划模块职责,而非事后调整。

4. 实际应用场景

  • 简单任务:若功能单一(如输出200以内平方数),单函数实现可能已满足高内聚。
  • 复杂任务:按"输入-计算-输出"拆分模块,确保各模块功能独立且接口简洁。

总结

你的笔记抓住了核心思想,但需更精准地定义"功能单一性"和"依赖关系",并辅以具体示例。高内聚低耦合的本质是模块职责清晰化交互最小化,通过合理设计提升代码的可维护性和可重用性。

相关推荐
Jooolin2 分钟前
Linux指令和Windows的有啥不一样?咋用的?
linux·操作系统·ai编程
Linux技术支持工程师17 分钟前
三十四、【Linux常用工具】rsync+inotify实时同步演示
linux·运维·服务器·学习·kylin
菜还不练就废了28 分钟前
7.25 C/C++蓝桥杯 |排序算法【下】
c语言·c++·排序算法
饭碗的彼岸one1 小时前
重生之我在10天内卷赢C++ - DAY 2
linux·开发语言·c++·笔记·算法·vim
程序员编程指南1 小时前
Qt 移动应用性能优化策略
c语言·开发语言·c++·qt·性能优化
梦在深巷@11 小时前
ica1靶机练习
linux·运维·服务器
岚天start1 小时前
Linux ps -ef 命令解析
linux·运维·服务器·ps·ef
qing222222221 小时前
记录Linux下ping外网失败的问题
linux·服务器·网络
Linux技术支持工程师1 小时前
三十二、【Linux网站服务器】搭建httpd服务器演示虚拟主机配置、网页重定向功能
linux·服务器·chrome
only_Klein2 小时前
openeuler24.03部署k8s1.32.7高可用集群(三主三从)
linux·kubernetes