一丶C语言的组成 1丶词法符号 (1)关键字(32个): 由编译器预先 定义的有特殊功能的单词短语 a类型相关的 基本数据类型: char double float int long short signed unsighed void 构造数据类型: struct union enum b存储相关:auto const extern register static c结构相关 :break case continue default do while if else for goto return switch d特殊功能 :sizeof typedef volatile (2) 运算符: 表示某种操作运算符符号 a.算数运算符: +(加 ) -(减) *(乘) /(除) %(求余或求模 ) C语言其他数学运算没有对应运算符,但 可以通过math库 实现 b.逻辑运算: 真 与 假的 运算 若结果为真(1),反之结果为假(0) 逻辑与 && 双目运算 真 && 真 结果为真 一假得假 逻辑或 || 双目运算 假 || 假 结果为假 一真得真 逻辑非 ! 单目运算 !真 == 假 补充:双目运算: 需要两个数参与的运算符 单目运算:只需要一个数参与运算 c.关系运算 大小比较 结果 真或假 > < == != >= <= d.位运算 计算机中特有的运算 所有运算目标 均针对二进制而言 按位 与 & 将二进制中的每一位进行与操作 与0得0 与1不变 按位 或 | 将二进制中的每一位进行或操作 或1得1 或0不变 按位取反 ~ 单目运算 按位异或 ^ 相同为0 不同为1 异或经典案例:交换a,b的值 a = a ^ b; ===> a ^= b; b = b ^ a; ===> b ^= a; a = a ^ b; ===> a ^= b; 移位运算 逻辑左移 << 高位移出丢弃 低位补0 算数右移 >> 低位移出对齐 无符号数 高位补0 有符号数 高位补符号位 e.选择运算 三目运算符: a ? b : c; 逻辑: 若a 为真 则 执行 b; 表达式的值 为 b 若a 为假 则 执行 c; 表达式的值 为 c f.逗号运算符, 表达式1, 表达式2, ... 表达式n; 运算逻辑, 每个表达式都执行一下, 整个表达式的值 为 表达式n 的值 a = 5, b = 10; z = (x+=5, y = x+0.2); &变量名 取地址符 得到变量的内存首地址 只能对变量或有内存空间的 量使用 g.自增自减运算符 ++ -- 单目运算 前缀++ 运算符 ++a; 先+ a=a+1 后用 后缀++ 运算符 a++; 先用 后+ a=a+1 指a++表达式结束 前缀-- 运算符 --a; 先- a=a-1 后用 后缀-- 运算符 a--; 先用 后- a=a-1 补充:表达式: 运算符 优先级 1. 优先级提升运算符 () 2. 单目运算符 优先级高 ++ -- & + - ! ~ 3. 算数运算符 高于 移位运算 高于 关系运算 高于 位运算 高于 逻辑运算 4. 吊车尾 3兄弟 三目运算 赋值运算 逗号运算符 (3)标识符: 由编程者 自定义的 名字 (4) 分隔符: 用于排版,方便阅读,美观, 但对编译没有任何影响 (5)标点符号:一些有特定位置 特定情况使用的标点符号,参与编译的需严格按照规范使用
2丶结构语法 (1)顺序结构 从上到下依次执行
(2)分支结构 需要根据条件 选择性执行某些代码或跳过某些代码 二分支: if ...else和switch...case if 语句 if( 条件表达式 ) { 语句块1; //当 条件表达式 的值为 真 时 语句块1执行 } else { 语句块2; //当 条件表达式 的值为 假 时 语句块2执行 }
格式简化或变种: 1. 语句块 只有一行C代码 即只有一个; 结束 代码块的 {} 可以省略不写 2. else 部分 没有代码 else {} 都可以省略
if嵌套: 即 if的代码块中包含 if结构
多分支:
switch( 整型表达式 ) { case 常量整型表达式1: 语句块1; break; case 常量整型表达式2: 语句块2; break; ..... default: 语句块n; }
整型表达式: 表达式的值 是一个整数 可以有变量 a / 10; 常量整型表达式: 表达式的值 是一个整数 不能有变量 5+3; 运算逻辑: 计算 整型表达式 的值, 依次 从上到下 与 case 中的 常量整型表达式 的值 比较 == 若相等, 则 执行 对应case 后的 语句块, 若 遇到break关键字 退出switch结构 若 没有break关键字 继续向下执行 后续case中的语句块 若不相等 则 继续向下比较 其他case中的值 default 语句块 在 没有命中 case中的值时 执行该语句块 若一直没有break关键字,也会执行到default 语句块 若不需要 default也可以省略 使用注意: 1.switch结构只对整型结构有效 2. 不能对变量进行case 3. case中的值不能存在相等的
(3)循环结构 根据条件 对某些代码 重复执行 while 循环 结构: while( 条件表达式 ) { 循环语句块; } 执行逻辑: 1.先判断 条件表达式的 真假 若真: 执行一次循环语句块; 再回到动作1 若假: 退出循环 即循环结束了
do while循环 结构: do{ 循环语句块; }while( 条件表达式 ); 执行逻辑: 1. 先执行一次 循环语句块; 2. 再 判断 条件表达式的 真假 若真: 执行一次循环语句块; 再回到动作2 若假: 退出循环 即循环结束了 for循环 结构: for( 循环初始化语句 ; 循环条件表达式 ; 递进表达式 ) { 循环体; } 执行逻辑: 1. 先执行一次 循环初始化语句 2. 判断 循环条件表达式 的真假 若真 执行 循环体一次; 在执行一次递进表达式; 回到 动作2 若假 退出 循环 递进表达式: 即使continue提前结束了本次循环,下一次循环开始前 递进表达式 也要执行 缩略写法: 若 循环初始化语句 没有 可以不写 若 循环条件表达式 不写 表示一直为真 若 递进表达式 不需要 也可以省略不写
死循环: for(;;) {}
while(1) {} 循环控制关键字: break; 提前跳出循环 不执行循环了 对于嵌套循环 只能跳出本循环 continue; 继续 提前结束 本次循环 重新开始下一次循环 goto 程序跳转关键字 只能在同一个函数中进行跳转
二丶Linux系统简单的命令 Linux系统的优点: 一个开源 免费的 多任务 多用户的 操作系统 可移植性好 可以裁剪 GNU组织, GPL协议 开源共享协议 Android 是一个Linux的应用程序 本文议Ubuntu16.04 虚拟机为例: 图形界面 与 Windows 类似 终端: 一个链接计算机的 命令窗口 ctrl + alt + t 打开一个新终端窗口 ctrl +shift + t 在同一个窗口中打开新终端 在一个窗口中切换终端 alt + 1 切换到窗口1 alt + 2 切换到窗口2
终端清屏命令 clear 快捷键 ctrl + l ls 命令 查看当前工作目录 中的文件或目录 ls -l 查看目录的详细内容
cd 命令 进入目录 cd 目录名 进入该目录 cd .. 返回上一级目录
删除文件和目录 rm 文件或目录名 -rf 递归删除文件或目录中的所有内容
创建目录 :mkdir 目录名
创建一个普通文件:touch 普通文件名
vim 字符界面 文本编辑器 来编写C代码 vim 文件名 打开文本文件 若该文件不存在 将会自动创建
vim 命令模式: 默认进入vim 就是命令模式 该模式下 键盘输入的都认为是命令 dd 剪切一行 光标所在行 10dd 剪切10行 光标所在行以及后边9行 p 粘贴 在光标下一行 粘贴 yy 复制光标所在行 10yy 复制光标所在行以及后边9行 x 删除光标所在字符 u 撤回上一次操作
进入 插入模式 命令模式下 输入 i o a i 进入插入模式 从光标位置前开始插入 o 进入插入模式 从光标下新建一行并从该行开头插入 a 进入插入模式 从光标位置后开始插入
退出插入模式 到 命令模式 esc
进入底行模式 该模式下 主要是操作文件 保存 退出 等 :wq 保存退出 :q! 强制退出 不保存 :w 仅保存 :wqa 保存并退出所有文件 多文件编辑 vim 1.c hello.c -o -o水平切分窗口 -O 垂直切分窗口
gcc hello.c 默认生成一个 a.out文件 就是该工程的可执行文件
运行可执行文件 :./a.out
Linux重命名文件 mv 命令 可以移动或重命名文件 mv hello.c 2.c 修改hello.c 为 2.c
三丶C语言的数据类型 数据类型: 即 对 不同类型的数 的 表示 和 存储
1.整数类型 精确类型 char 字符型 8bit 1字节 存储这个数 0-255 共256个数 short 半字类型 16bit 2字节 0-2^16-1 = 65535 int 整型 32bit 4字节 0-2^32-1 = 4,294,967,295 long 长整型 64bit 8字节 0-2^64-1 = ...............
signed 有符号类型 不写默认是有符号类型 unsigned 无符号类型
signed char 有符号字符型 -128 ~ + 127 unsighed char 无符号字符型 有符号数 最高bit 作为符号位 0 正数 1 负数 signed char -128 ~ 0 ~ +127 补码形式 存储有符号类型 LinuxC中: 不写 signed 默认 都是有符号 gcc 单片机C中 arm gcc char 不写 默认无符号类型 除char类型 外 其他不写signed 默认是有符号类型 最高位 为 符号位 其余位 存储值 若值是负数 补码 负数值 = 补码取反 +1
2.小数: 2.5 0.71231 0.00002566335225560216 21865862522568685235.562525255252265 非精确类型: 数据 有 有效位数 超过有效位数的数据丢弃
浮点数存储: flaot 单精度浮点型 4字节存储 有效十进制位数 约6位 最高bit 符号位 8bit 幂指数位 23 位有效位 double 双精度浮点型 8字节存储 有效十进制位数 约15位 最高bit 符号位 11bit 幂指数位 52 位有效位 3.布尔类型 bool 真 假 有一些运算 或操作 其结果是布尔类型 关系运行 逻辑运算 C语言中 真 非0 为真 0假 4.void 类型 空类型 5.常量: 程序运行过程中 始终不变的量 整型常量: 5 10 -5 整数值 8 浮点常量: 2.5 -3.7 指数常量: 3.0e-26 => 3*10^-26 字符常量: 单个英文字符 'a' '8' === 56 ASCII 字符串常量: 多个字符放在一起 "hello world" 在内存中 存储的是 字符的 编码 连续存储 在内存中 存储的是 字符的 编码 连续存储 标识常量(宏定义): 本质是给 常量 定义一个字符串形式的 别名 #define 宏名 值 #define PI 3.14 #define WATER 3.0e-26
四丶C语言中的变量 变量: 程序运行过程中 可能改变的量 其本质 即 给一个 内存空间 命名 通过该名字访问内存 C语言中 的 变量 1. 先定义在使用 2. 定义时给定类型 一旦定义完成 其类型将不能改变 常量或代码: a.out 1.代码段: 存储代码 即编译的二进制指令 只读 2.常量区: 存储程序中的 常量 "" 的部分 常量字符串 只读 可以使用 const 关键字 修饰全局变量 将该变量的存储位置 变更为常量区 变量: 3.静态区: 可读可写 只能被初始化 一次 在程序开始运行时 该区域变量 将从程序开始 一直存在到程序结束 未初始化的 静态区变量 都默认初始化为0 4.堆区: 有程序员 在程序运行时 可以手动 动态(长度不确定)申请或释放的 内存 5.栈区: 有程序运行时 自动(函数形参或局部变量) 申请或释放的 内存 未初始化的栈区堆区变量 其初始值不确定 由系统维护的数据: 6.系统区: LinuxC有, 存储操作系统对于该进程的 一些数据 进程控制块,内存占用情况, 环境变量等 只读
全局变量: 变量定义的位置 在函数外(不在任何函数内 {}) 可以在整个程序中使用 局部变量: 变量定义的位置 在函数内( 在 {} 中定义的) 只能在{}内部使用
auto 修饰全局变量 该变量存储与 静态区 auto 修饰局部变量 该变量存储与 栈区 const 修饰全局变量 该变量存储与 常量区 static 修饰局部变量 该变量存储与 静态区 只能在{}内使用 只能被初始化 一次 在程序开始运行时 static 修饰全局变量 该变量存储与 静态区 只能在当前C文件中使用 只能被初始化 一次 在程序开始运行时 多用于防止全局变量重名 导致的问题 static 修饰函数 该函数只能在 本文件内使用
变量赋值 变量名 = 值; 即 向内存中 写入值 变量初始化 即 定义时 赋值
extern 修饰全局变量 表示外部 引入 存储类型 不开辟新的内存 空间 是一种声明 extern 函数 表示引入外部文件实现的 函数
register 寄存器类型 声明 表示变量 尽量使用寄存器存储 通常用于修饰 在一段代码中 使用极其频繁的 量 该存储类型的变量 不能取地址 &
变量名: 由编程者 自己定义的名字 程序中 变量名 函数名 宏名 都是 标识符 命名规范: 1. 只能由 字母 数字 下划线 组成 区分大小写 2. 不能由数字开头 3. 不能与 关键字重名 32个
2.数据类型的转换过程: float ---> int 舍弃小数 取整操作 int ---> float 整型(精确类型) 小数(非精确类型) 精度会丢失 int ---> char 溢出部分舍弃 宽存储空间 转换为 小存储空间 int ---> short 小存储空间 转换为 宽存储空间 不影响
整型与浮点型 参与运算时 隐式类型转换 会统一转换为浮点型计算 有符号数 无符号数 强制类型转换时 存储内容 完全没有改变 但影响计算
五丶字符串的输入输出 C语言中标准输入与输出: 标准输入: 程序终端 输入的内容 标准输出: 程序输出 到终端显示 使用: format 格式控制字符串 "a=%d\n",a 其中 a=\n 原样输出 %d 格式占位控制符
%d 输出整型有符号数 以10进制方式显示 %x 输出整型无符号数 以16进制方式显示 %u 输出整型无符号数 以10进制方式显示 %c 输出一个 字符型数 以字符方式显示 %s 输出一个字符串 以\0 作为结束符 %f 输出一个浮点类型 以10进制方式 %% 输出%本身
附加格式说明符(修饰符): %8d 输出整型有符号数 以10进制方式显示 在数据值宽度低于8个字符位置时 填充空格维持8个字符位置 -8 向左对齐 8 默认右对齐 %.2f 输出一个浮点类型 以10进制方式 保留2位小数 四舍五入
%ld 输出整型有符号数 宽度为8字节long 以10进制方式显示 %lf 输出 double 类型的浮点数
格式控制字符串: 非常类似于printf %d 表示 输入提取为一个整型数 %f 表示 输入提取为一个小数数 %4d 表示 输入提取为一个整型数 宽度为4个数字 %4c 表示 输入提取4个字符 组成字符串 %s 输入一个字符串 默认以空格 或 回车 或 制表符(tabl)
六丶数组与函数
构造数据类型: 有程序员设计的数据类型 基于基本数据类型的组合 数组: 将多个 相同类型的 数据 连续,有序存放 构成的数据类型 称数组 数组的元素: 即 数组中的每一个数据 1.数组 数组定义: 存储类型 元素数据类型 数组名[元素个数];
示例: 存储5个整型 元素的数组 int arr[5]; 数组的初始化: 定义数组时给定 初始值 int arr[5] = {初始化表}; int arr[5] = {1,2,3,4,5};
int arr[5] = {1,0,2}; //初始化表 没有包含全部元素, 剩余元素默认赋值为0 int arr[] = {1,2,3,4}; //定义数组时, 没有给定元素个数,但有初始化表 //则 数组的个数将由 初始化表中元素个数决定 int arr[]; // 不能这样定义 , 编译器无法确定你元素的个数 int arr[5] = {0}; //将数组元素全部初始化为0 int arr[5]; 数组定义时 元素个数 必须预先已知和确定 即 定义数组时 其元素个数不能是变量 即 程序运行起来前, 数组元素个数应该已经确定
数组的使用: 元素访问: 读 写 数组中的元素 使用 [] 元素访问运算符 示例: 数组名[元素下标]; 元素下标: 数组中的元素 从0开始 自左向右依次编号 //元素下标 可以是整型表达式 数组的遍历: 即 将数组中的 每个元素都访问一次 for(int i=0;i < sizeof(arr)/sizeof(arr[0]) ; i++)
for(int i = sizeof(arr)/sizeof(arr[0]) -1; i >= 0; i--)
数组名: 1. 代指这个数组本身 数组名[下标]; sizeof(arr); 2. 代指这片内存空间的 首地址 printf("%p",arr); //arr == &arr[0]
数组的内存模型: 数组占用空间 为 元素个数 * 每个元素的长度 &arr[0]; 该表达式 表示 取 数组arr中 0号元素的 地址
字符串拷贝 :输入一个字符串到 buf中 拷贝buf中的字符 到 char arr[20];数组中 去除'\n' 字符串拷贝函数 #include <string.h> char *strcpy(char *dest, const char *src); 将字符串 src 拷贝一份到 dest 空间中 char *strncpy(char *dest, const char *src, size_t n); 将字符串 src 拷贝一份到 dest 空间中 n 表示需要拷贝的字符个数
字符串的比较: #include <string.h>
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n); 比较两个字符串 s1 和 s2 相等 返回 0 != 0 不相等
2.二维数组 二维数组: 即 数组中的元素 是一个数组(一维数组)
成绩表: 将多个 相同类型的 数据 连续,有序存放 构成的数据类型 称数组 二维数组: 定义 int arr2[2][3]; 初始化: int arr2[2][3] = {{88,79,99},{78,100,60}}; int arr[3] = {88,79,99}; arr[0] 二维数组的存储模型, 数组的访问模型; 二维数组在逻辑上可以表示 行列 平面模型 在存储上 按行列展平存储 3.函数 函数: 完成特点功能的 代码块的集合 函数 输入和 输出: 输入: 终端输入 参数输入 硬件输入 可以没有输入 sleep(); delay(); 延时1us 输出: 终端输出 返回值输出 硬件输出 其他的逻辑输出 任何函数都有输出 函数的意义: 1. 对功能代码 的 封装 方便于多文件开发 2. 提高代码的 复用性 1. 定义函数 返回值类型 函数名(参数列表) { 函数体; }
返回值类型: 一个函数 可以有返回值 也可以没有 void修饰 int float char 返回值可以在 4或8字节 通常 返回值 1.表示函数执行成功或不成功的标志 2.返回一些 简单的结果
函数名: 标识符 由编程者自己定义 通常根据其功能命名 "123" == int 123; atoi (参数列表) : 用于调用函数时 传递给函数的 一些参数 也可以没有参数 void修饰 或 不写 () : 可能有参数 但我用不到 (void) : 肯定没有参数 一个函数的 参数 可能不止一个 多个参数用,逗号 隔开 函数体: 该函数功能实现的 逻辑代码 函数需要调用才能 得以执行,, 什么时候调用 由调用者决定 函数名(实参列表); //若被调用的函数不需要参数 就 不写 实参列表 应该与 形参列表 一一对应 不能多也不能少 参数类型要一致 函数原型: 除了函数体 外 的部分 称函数原型 函数声明: 即在 函数调用前 声明一下该函数 将该函数的原型 写到调用前