C语言基础部分
C语言关键字:32个
1.类型相关的
基本数据类型: char double float int long short signed unsighed void
构造数据类型: struct union enum
2.存储相关
auto const extern register static
3.结构相关
break case continue default do while if else
for goto return switch
4.特殊功能
sizeof typedef volatile
C语言中,对数 设计类型:
数据类型: 即 对 不同类型的数 的 表示 和 存储
整数类型 精确类型
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 =
int 与 long 存储大小
一些8位单片机 51 int 2字节 long 4字节
一些32位单片机 stm32 或 LinuxC int 4字节 long 8字节
signed 有符号类型 不写默认是有符号类型
unsigned 无符号类型
signed char 有符号字符型 -128 ~ + 127
unsighed char 无符号字符型
变量: 程序运行过程中 可能改变的量
其本质 即 给一个 内存空间 命名 通过该名字访问内存
C语言中 的 变量 1. 先定义在使用 2. 定义时给定类型 一旦定义完成 其类型将不能改变
示例 变量的定义:
存储类型 数据类型 变量名;
auto int a; // 即表示 声明一段4字节内存空间 命名为 a
若省略存储类型 即 auto 类型
存储类型: 决定了 变量存储的位置
C语言内存结构:
常量或代码: 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个
int 张3; int 7a; int char; 不行
int _abc; int printf; 可以
库标识符: 库中 有对于该标识的定义
系统标识符: 由编译定义了的 include
数据类型的转换: 将类型不匹配 的数据 转换为 对应匹配类型的数据格式
隐式类型转换: 有编译器 自动完成 一些默认转换模式
强制类型转换: 编程者 手动进行的 强制性的类型 转换
变量 或 值 前 使用(目标类型)
类型的转换过程:
float ---> int 舍弃小数 取整操作
int ---> float 整型(精确类型) 小数(非精确类型) 精度会丢失
int ---> char 溢出部分舍弃 宽存储空间 转换为 小存储空间
int ---> short
小存储空间 转换为 宽存储空间 不影响
整型与浮点型 参与运算时 隐式类型转换 会统一转换为浮点型计算
有符号数 无符号数 强制类型转换时 存储内容 完全没有改变 但影响计算
C语言中标准输入与输出:
标准输入: 程序终端 输入的内容
标准输出: 程序输出 到终端显示
输出: 使用man 函数名 查询该函数
putc(); 输出一个字符 'a'
putchar(); 与putc一样
puts(); 输出一个字符串 "hello world"
格式化输出函数
printf();
#include <stdio.h>
int printf(const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
sprintf/snprintf 即格式化后 输出到 指定内存容器str中
返回值: 成功 返回 格式化后输出的字符个数
... 变长参数个数
使用: 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 类型的浮点数
标准输入:
#include <stdio.h>
int fgetc(FILE *stream); //得到一个字符
int getc(FILE *stream); //得到一个字符
int getchar(void); //得到一个字符
char *fgets(char *s, int size, FILE *stream); //得到一行输入
s: 存放输入字符串的容器 char buf[20];
size: 容器的大小 单位字节
stream: stdin
scanf: 格式化输入
int scanf(const char *format, ...);
int sscanf(const char *str, const char *format, ...);
sscanf 从str内存中 按格式提取
格式控制字符串: 非常类似于printf
%d 表示 输入提取为一个整型数
%f 表示 输入提取为一个小数数
%4d 表示 输入提取为一个整型数 宽度为4个数字
%4c 表示 输入提取4个字符 组成字符串
%s 输入一个字符串 默认以空格 或 回车 或 制表符(tabl)
返回值 表示成功的提取项的个数 。
C语言中 可以支持的运算符有:
1.算数运算符: +加 -减 *乘 /除 %求余 求模
/除 5 / 3 == 1 整数除法是求商 浮点数除法 结果为浮点数
%求余 必须是整数 5 % 3 == 2
其他数学运算 没有对应运算符 可以通过math库 实现
双目运算: 需要两个数参与的运算符
2.逻辑运算: 真 与 假的 运算
符号
逻辑与 && 双目运算 真 && 真 结果为真 一假得假
逻辑或 || 双目运算 假 || 假 结果为假 一真得真
逻辑非 ! 单目运算 !真 == 假
非0 为真 0假
5 || 0 结果 真 1
5 && 0 结果 假 0
!0.5
3.关系运算 大小比较 结果 真或假
> < == != >= <=
4.位运算 计算机中特有的运算 所有运算目标 均针对二进制而言
按位 & 将二进制中的每一位进行与操作 与0得0 与1不变
按位 | 将二进制中的每一位进行或操作 或1得1 或0不变
按位取反 ~ 单目运算
按位异或 ^ 相同为0 不同为1
移位运算
逻辑左移 << 高位移出丢弃 低位补0
算数右移 >> 低位移出对齐 无符号数 高位补0 有符号数 高位补符号位
C语言中的结构性语句:
1.顺序结构 从上到下依次执行
2.分支结构 需要根据条件 选择性执行某些代码或跳过某些代码
3.循环结构 根据条件 对某些代码 重复执行
分支结构:
二分支:
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中的值不能存在相等的
循环结构:
通常在程序中 需要反复执行某些动作, 则需要循环
即在某些情况下,程序会跳转到前面去继续执行代码
while 循环
结构:
while( 条件表达式 )
{
循环语句块;
}
执行逻辑:
1.先判断 条件表达式的 真假
若真: 执行一次循环语句块; 再回到动作1
若假: 退出循环 即循环结束了
do while循环
结构:
do{
循环语句块;
}while( 条件表达式 );
执行逻辑:
1. 先执行一次 循环语句块;
2. 再 判断 条件表达式的 真假
若真: 执行一次循环语句块; 再回到动作2
若假: 退出循环 即循环结束了
结构:
for( 循环初始化语句 ; 循环条件表达式 ; 递进表达式 )
{
循环体;
}
执行逻辑:
1. 先执行一次 循环初始化语句
2. 判断 循环条件表达式 的真假
若真 执行 循环体一次; 在执行一次递进表达式; 回到 动作2
若假 退出 循环
递进表达式: 即使continue提前结束了本次循环,下一次循环开始前 递进表达式 也要执行
缩略写法:
若 循环初始化语句 没有 可以不写
若 循环条件表达式 不写 表示一直为真
若 递进表达式 不需要 也可以省略不写
死循环:
for(;;)
{}
while(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--)
除初始化外, 数组不能 通过元素列表方式赋值
arr = {1,2,3,4,5}; // 不行 C语言 不支持
数组名:
1. 代指这个数组本身 数组名[下标]; sizeof(arr);
2. 代指这片内存空间的 首地址 printf("%p",arr); //arr == &arr[0]
数组的内存模型:
数组占用空间 为 元素个数 * 每个元素的长度
&arr[0]; 该表达式 表示 取 数组arr中 0号元素的 地址