这是我在职坐标学习编程的第一周知识总结,仅供参考学习。
基本数据类型、变量、常量、关键字、转义字符、键盘录入:
基本的数据类型如下
| 类型 | 典型大小 (字节) |
范围 | 格式 占位符 |
|---|---|---|---|
| int | 4 | -231 ~231-1 | %d |
| short | 2 | -32768~32767 | %hd |
| long | 4/8 | 平台相关 | %ld |
| longlong | 8 | -263 ~ 263-1 | %lld |
| char | 1 | -128~127 | %c |
| float | 4 | $\pm$3.4E+38(约7位有效数字 | %f |
| double | 8 | ±1.7E+308(15位有效 | %lf |
整数类型:char short int long longlong 可以被unsigned关键字修饰,表明变量没有符号位,即变量只能是非负整数。
变量:
概念:变量是内存中一块有名字的储存空间,用于储存可变的数据。
// 变量的定义与初始化: 数据类型 变量名 = 数据;
int age = 20; // 定义并初始化
float price; // 只定义,未初始化
char ch = 'A'; // 字符变量
double pi = 3.14159 // 双精度浮点数
命名规则:1,只能由字母、数字、下划线组成。2,不能以数字开头。3,不能使用关键字(变量名不能是关键字)。4,区分大小写(Age不等于age,二者不是同一个变量)
变量必须先定义后使用。
常量:
概念:程序运行过程中不可改变的量。
| 常量类型 | 示例 | 说明 |
|---|---|---|
| 整型字面常量 | 100,-50,0 |
直接写的整数 |
| 浮点字面常量 | 3.14,1.5e10 |
直接写的小数 |
| 字符字面常量 | 'A','0','\n' |
单引号包裹的单个字符 |
| 字符串字面常量 | "Hello","123" |
双引号包裹的字符序列 |
const常变量 |
const int MAX = 100; |
有类型的只读变量 |
#define宏常量 |
#define PI 3.14 |
预处理阶段直接替换 |
| 枚举常量 | enum { MON, TUE, WED }; |
自动从0开始编号 |
const:有类型检查,编译器阶段处理
define :无类型检查,预处理阶段文本替换
字符常量 'A'占一个字节,字符串常量 "A"占2个字节包含末尾隐藏的\0
关键字:
概念:C语言预先保留的、具有特殊含义的英文单词,不能用作变量名、函数名。C语言一共32个关键字。
| 分类 | 关键字 | 用途 |
|---|---|---|
| 数据类型 | int,char,float,double,void,long,short,signed,unsigned |
声明变量类型 |
| 类型修饰 | const,volatile,enum,struct,union |
修饰或定义复合类型 |
| 存储类别 | auto,static,extern,register |
控制变量的存储方式和生命周期 |
| 流程控制 | if,else,switch,case,default,for,while,do,break,continue,return,goto |
控制程序执行流程 |
| 运算符 | sizeof |
获取类型/变量大小 |
sizeof是关键字不是函数,且sizeof()里面如果有运算表达式之类的,不会进行计算,只会计算表达式类型所占的字节。
int i =0;
sizeof(i++);// 结果是4或者8等同sizeof(int)
printf("%d",i); // 输出结果是0,i++不会进行计算
static关键字的作用:修饰局部变量延长生命周期,修饰全局变量、函数限制作用域。
作用域:变量在代码中能被访问的代码区域;生命周期:变量在运行期在内存中实际存活的时间。
转义字符:以\开头,将字符转义为特殊含义的字符序列
| 转义字符 | 含义 | ASCII值 | 使用场景 |
|---|---|---|---|
\n |
换行 | 10 | 最常用,输出换行 |
\t |
水平制表 | 9 | 对齐输出 |
\\ |
反斜杠 | 92 | 表示路径中的\ |
\' |
单引号 | 39 | 在字符常量中表示' |
\" |
双引号 | 34 | 在字符串中表示" |
\0 |
空字符 | 0 | 字符串结束标志 |
\r |
回车 | 13 | 回到行首(不换行) |
\a |
警报/响铃 | 7 | 发出提示音 |
\xNN |
十六进制 | NN | 如\x41→'A' |
\NNN |
八进制 | NNN | 如\101→'A' |
键盘录入:通过scanf函数从键盘读取用户输入的数据
// 基本语法:scanf("格式控制字符串", 地址列表);
int age;
scanf("%d", &age); // ⭐ 注意 & 取地址符!
float score;
scanf("%f", &score);
char ch;
scanf("%c", &ch);
char name[50];
scanf("%s", name); // 数组名本身就是地址,不需要 &
| 格式符 | 对应类型 | 说明 |
|---|---|---|
%d |
int |
读取整数 |
%f |
float |
读取单精度浮点 |
%lf |
double |
读取双精度浮点 |
%c |
char |
读取单个字符(包括空格和回车) |
%s |
char[] |
读取字符串(遇空格停止) |
scanf 需要通过地址来修改变量的值,普通变量必须加&
操作符
算数操作符:进行基本的四则运算
| 操作符 | 名称 | 示例 | 说明 |
|---|---|---|---|
+ |
加 | a + b |
常规加法 |
- |
减 | a - b |
常规减法 |
* |
乘 | a * b |
常规乘法 |
/ |
除 | a / b |
整数除法会截断小数 |
% |
取模(取余) | a % b |
只能用于整数,返回余数 |
两个整数相除时,结果还是整数,小数部分会被截断。除数不能为0;
int a = 7 / 2; // 结果是 3,不是 3.5
float b = 7.0 / 2; // 结果是 3.5(有浮点数参与则按浮点运算)
赋值运算符:将右侧表达式的值存入左侧变量
| 操作符 | 示例 | 等价写法 |
|---|---|---|
= |
a = 10 |
基本赋值 |
+= |
a += 5 |
a = a + 5 |
-= |
a -= 3 |
a = a - 3 |
*= |
a *= 2 |
a = a * 2 |
/= |
a /= 4 |
a = a / 4 |
%= |
a %= 3 |
a = a % 3 |
关系操作符:比较2个值的大小或者相等关系,结果为0或1;
| 操作符 | 含义 | 示例 |
|---|---|---|
| > | 大于 | a > b |
| < | 小于 | a < b |
>= |
大于等于 | a >= b |
<= |
小于等于 | a <= b |
== |
等于 | a == b |
!= |
不等于 | a != b |
注意:不能连续比较 如 1>2>3;
逻辑操作符:
| 操作符 | 名称 | 规则 | 示例 |
|---|---|---|---|
| && | 逻辑与 | 两边都为真才为真 | a > 0 && a < 10 |
|| |
逻辑或 | 一边为真即为真 | a > 0 || a > 100 |
! |
逻辑非 | 真变假,假变真 | !(a == 0) |
重点:短路
&&:左边为假,右边不执行,因为结果必然是假
||:左边为真,右边不执行,因为结果必然为真
一般 0表示假 1表示真;
位操作符
| 操作符 | 名称 | 规则 | 示例 |
|---|---|---|---|
| & | 按位与 | 同为1才为1 | 5 & 3→0101 & 0011=0001(1) |
| |
按位或 | 有1就为1 | 5 | 3→0101 | 0011=0111(7) |
^ |
按位异或 | 不同为1 | 5 ^ 3→0101 ^ 0011=0110(6) |
~ |
按位取反 | 0变1,1变0 | ~5→~0101=...1010(-6) |
<< |
左移 | 高位丢弃,低位补0 | 5 << 1→1010(10) |
>> |
右移 | 低位丢弃,高位补符号位 | 5 >> 1→0010(2) |
位运算小技巧:1判断奇偶数:n&1(等于1为奇数,等于0为偶数);2交换两个数不用临时变量: a ^= b; b ^= a; a ^= b;
单目操作符:只有一个操作数的操作符
| 操作符 | 名称 | 说明 |
|---|---|---|
++ |
自增 | 前置++i(先加后用)vs 后置i++(先用后加) |
-- |
自减 | 同自增,前置--ivs 后置i-- |
+ |
正号 | 通常省略 |
- |
负号 | 取负值 |
! |
逻辑非 | 真变假(0),假变真(1) |
~ |
按位取反 | 二进制位全部取反 |
& |
取地址 | 获取变量的内存地址 |
* |
解引用 | 通过指针访问指向的值 |
sizeof |
类型/变量大小 | 是操作符不是函数,结果为字节数 |
条件操作符、逗号操作符,条件操作符又称三目运算符
// 条件操作符
// 语法:条件 ? 表达式1 : 表达式2
int max = (a > b) ? a : b; // 等价于 if(a>b) max=a; else max=b;
// 逗号
// 语法:表达式1, 表达式2, ..., 表达式N
int result = (a = 1, b = 2, a + b); // result = 3(取最后一个表达式的值)
操作符的优先级:
| 优先级 | 操作符 | 名称 | 结合性 |
|---|---|---|---|
| 1(最高) | () [] . -> ++(后) --(后) | 括号、下标、成员、后缀自增自减 | 从左到右 |
| 2 | ! ~ ++(前) --(前) +(正) -(负) *(解引用) &(取地址) sizeof | 单目操作符 | 从右到左 |
| 3 | * / % | 乘、除、取模 | 从左到右 |
| 4 | + - | 加、减 | 从左到右 |
| 5 | << >> | 移位 | 从左到右 |
| 6 | < <= > >= | 关系比较 | 从左到右 |
| 7 | == != | 相等判断 | 从左到右 |
| 8 | & | 按位与 | 从左到右 |
| 9 | ^ | 按位异或 | 从左到右 |
| 10 | | | 按位或 | 从左到右 |
| 11 | && | 逻辑与 | 从左到右 |
| 12 | || | 逻辑或 | 从左到右 |
| 13 | ? : | 条件操作符 | 从右到左 |
| 14 | = += -= *= /= %= &= ^= |= <<= >>= | 赋值操作符 | 从右到左 |
| 15(最低) | , | 逗号操作符 | 从左到右 |
流程控制语句
一顺序结构:程序最基本的执行方式,代码自上而下、逐行一次执行,无跳转、无判断
一分支结构,选择结构
一.1if语句,分三种,单if ,if....else.... 和if...else if....else..
// ① 单分支:条件为真才执行
if (score >= 60) {
printf("及格了!\n");
}
// ② 双分支:非此即彼
if (score >= 60) {
printf("及格\n");
} else {
printf("不及格\n");
}
// ③ 多分支(阶梯if):从上到下依次判断,命中一个就跳出
if (score >= 90) {
printf("优秀\n");
} else if (score >= 80) {
printf("良好\n");
} else if (score >= 60) {
printf("及格\n");
} else {
printf("不及格\n");
}
重点 — 条件判断的本质:if (表达式) 中,表达式结果为 0 视为假,非 0 视为真
重点 — 多分支的顺序性:else if 是从上往下依次判断的,一旦某个条件为真,后面的全跳过。所以条件的排列顺序很重要!
--2.switch语句
switch (day) { // 表达式必须是整数或字符
case 1: // case 后必须是常量
printf("周一\n");
break; // ⭐ 必须有 break,否则会"穿透"
case 2:
printf("周二\n");
break;
case 3: case 4: // 多个 case 共享同一段代码
case 5:
printf("工作日\n");
break;
default: // 可选:所有 case 都不匹配时执行
printf("周末\n");
break;
}
重点 — switch vs if 的选择:
switch:适合离散值/枚举判断(如星期、菜单选项、状态码)
if:适合范围/区间判断(如成绩分段、年龄范围)
易错 — case 穿透(Fall-through):忘记写 break,程序会继续执行下一个 case 的代码,直到遇到 break 或 switch 结束
易错 — case 后面必须是常量:不能是变量或表达式,如 case n: 或 case a+b: 是非法的
--.3循环控制语句
while循环(先判断,后执行)循环次数不确定,由条件控制
int i = 1;
while (i <= 10) { // 先判断条件
printf("%d ", i); // 条件为真才执行
i++; // ⚠️ 别忘了更新循环变量,否则死循环!
}
do-while循环 --先执行一次,再进行条件判断
int num;
do {
printf("请输入一个正数:");
scanf("%d", &num);
} while (num <= 0); // ⚠️ 注意这里的分号不能少!
适用场景:需要先执行一次才能判断的场景(如菜单系统、输入验证)
for循环 ,循环次数已知或可预计算(如遍历数组、固定次数操作)
// ①初始化 ②条件判断 ④步进更新
for (int i = 0; i < 10; i++) {
printf("%d ", i); // ③循环体
}
// 执行顺序:① → ② → ③ → ④ → ② → ③ → ④ → ... 直到②为假
for (int i=0, j=10; i < j; i++, j--) // 多变量初始化和步进
for (; condition; ) // 省略初始化和步进(等价while)
for (;;) // 三个都省略 = 死循环
// 循环控制:break,continue
// break:直接跳出整个循环
for (int i = 1; i <= 10; i++) {
if (i == 5) break; // 当 i=5 时,直接结束循环
printf("%d ", i); // 输出:1 2 3 4
}
// continue:跳过本次循环剩余代码,直接进入下一次循环
for (int i = 1; i <= 10; i++) {
if (i == 5) continue; // 当 i=5 时,跳过本次的 printf
printf("%d ", i); // 输出:1 2 3 4 6 7 8 9 10
}
循环语句切套使用:循环内部再包含循环,外循环每执行一次,内循环完整执行一轮
// 打印九九乘法表
for (int i = 1; i <= 9; i++) { // 外层:控制行数
for (int j = 1; j <= i; j++) { // 内层:控制每行的列数
printf("%d*%d=%-4d", j, i, i*j);
}
printf("\n"); // 每行结束后换行
}
//冒泡排序
// 将包含 n 个元素的数组 arr 按升序(从小到大)排列
void bubbleSort(int arr[], int n) {
// 【外层循环】控制“趟数”(宏观轮数)
// n 个元素,最多需要 n-1 趟就能全部排好
for (int i = 0; i < n - 1; i++) {
// 【内层循环】控制“每趟的比较次数”
// 第 i 趟结束后,末尾的 i 个元素已经排好,不需要再比了
// 所以每趟比较的范围是 0 到 n - 1 - i
for (int j = 0; j < n - 1 - i; j++) {
// 【分支结构】判断相邻元素是否需要交换
if (arr[j] > arr[j + 1]) {
// 【顺序结构】交换两个变量(必须借助临时变量)
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
函数
概念:函数是一段具有特定功能、可被重复调用的代码块。
设计原则:单一职责原则,一个函数只做好一件事,提高代码复用性
标准格式:
返回类型 函数名(参数列表) {
// 函数体:具体执行的过程
return 返回值; // 如果返回类型不是void
}
返回类型:
- 函数执行完毕后带回的结果类型。
- 如果不需要返回值,必须用
void声明(如纯打印功能)。 return语句后的数据类型必须与声明的返回类型一致。
函数名:
- 硬性规定:只能由字母、数字、下划线和
$组成,且数字不能开头,不能是关键字。 - 软性要求:见名知义,推荐使用驼峰命名法(如
getSum)或下划线命名法(如user_name
参数列表:
- 函数工作需要的“原材料”。格式为
数据类型 参数名,多个参数用逗号分隔。 - 必须指定数据类型。
函数不能嵌套定义,函数与函数之间是平级关系,必须并列定义在外部;
函数的调用:
int main() {
int sum1 = getSum(1, 2); // 传入具体值
int a = 10, b = 20;
int sum2 = getSum(a, b); // 传入变量
return 0;
}
参数匹配原则:调用时,实参的类型、个数、顺序必须与定义时的形参严格一致,否则会导致编译错误或隐式转换引发的逻辑错误。
函数的声明:在调用之前,提前告诉编译器后面有这么个函数
int getSum(int a, int b); // 函数声明(注意末尾有分号)
int main() {
getSum(1, 2); // 编译器放心让你调用
return 0;
}
int getSum(int a, int b) { return a + b; } // 函数定义
定义与声明的区别:声明不包含函数的具体执行内容代码,且必须在调用之前;
形参和实参:
| 概念 | 位置 | 本质 | 示例 |
|---|---|---|---|
| 形参 (形式参数) | 函数定义的括号内 | 本质是局部变量,用于接收数据 | int getSum(int a, int b)中的a, b |
| 实参 (实际参数) | 函数调用的括号内 | 具体传入的值或变量 | getSum(10, 20)中的10, 20 |
值传递:C语言中普通参数传递是单向的值拷贝。实参把值复制给形参,在函数内修改形参,不会影响外部的实参变量
地址传递:直接把变量的地址传给函数,函数可以通过地址来修改外部的实参的值。
变量的作用域与生命周期
| 变量类型 | 定义位置 | 作用域 (在哪能用) | 生命周期 (何时生,何时死) | 存储位置 |
|---|---|---|---|---|
| 局部变量 | 函数内 /{}内 |
仅在定义它的函数或代码块内 | 进入代码块创建,离开代码块销毁 | 栈区 |
| 全局变量 | 所有函数外部 | 整个程序的任何地方 | 程序启动时创建,程序结束时销毁 | 静态区 |
| 静态变量 ( static修饰) |
函数内/外 | 局部:仅本函数内 全局:仅本文件内 |
程序启动时创建,程序结束时销毁 (值保留) | 静态区 |
递归:函数在运行过程中调用自己
两大必要条件:
递归公式:将大问题拆解为与原问题相似的小问题(如 n! = n * (n-1)!)。
终止条件(基线条件):必须有明确的出口,否则会无限调用导致栈溢出 (Stack Overflow),程序崩溃。
int factorial(int n) {
if (n == 0 || n == 1) return 1; // 终止条件
return n * factorial(n - 1); // 递归调用
}

浙公网安备 33010602011771号