C语言笔记
适用:C语言基础、数组、函数、二分查找、双指针动画、运算符区分
一、运算符核心区分(高频坑点)
-
= 和 ==
-
= 赋值运算符:把右边的值,存到左边变量
有时候它定义时候的赋值是有意义的,大多数情况定义赋值为0不影响,因为后面会重新赋值覆盖它。但是如果定义赋值与后续的判断条件有关,那么就要注意了。就像那个第一位是打印数字一样。
int a = 5; // 将5赋值给a
int flag = 1;// flag=1代表真
- == 关系运算符(判断相等):比较左右两边,返回1(真) / 0(假)
c
if(a == 5) {} // 判断a是否等于5
if(flag == 0){} // 判断flag是否为假
❗易错:if里面千万别写成 if(a=5) ,这是赋值不是判断!
- 关系表达式(布尔表达式)
形如 num % 2 == 0 ,用来做真假判断。
C语言没有单独bool类型,非0就是真,0就是假。
可以直接把判断结果赋值给变量,用来保存状态。
int is_even = (num % 2 == 0);
// 如果num是偶数,is_even=1;奇数则is_even=0
if(is_even) // 等价 if(is_even != 0),简化写法
二、数组【重中之重,最容易混淆】
口诀:定义时给总数,访问时给位置
正真起作用的是下标
- 定义数组 int arr[5]
[5] 代表数组大小:一共可以存放5个int元素
下标范围: 0,1,2,3,4 - 访问数组 arr[3]
[3] 代表下标(索引),取数组里第4个元素。
核心区分:
- 写在变量定义那一行的 [] :数组容量(元素总个数)
- 定义完成后,代码里 arr[下标] :访问对应位置元素
技巧:下标不从0开始(人为空出arr[0])
目的:贴合现实编号,避免频繁 下标 = 编号-1
//问月份的时候 int arr[13]={0,31,29,31,30,31,30,31,31,30,31,31,31};
// 星期示例
char *week[] = {“”, “星期一”, “星期二”, “星期三”, “星期四”, “星期五”, “星期六”, “星期日”};
// week[1]直接是星期一
// 扑克牌
char *poker[] = {“”, “A”,“2”,“3”,…,“J”,“Q”,“K”};
// poker[1]=A,poker[13]=K
//学生成绩,学号1001开始
float scores[1010] = {0};
scores[1001] = 90; //学号1001的成绩
数组名知识点回顾
- 一维数组数组名 arr = &arr[0] ,首元素地址, scanf 不用加 &
- arr[i] 是单个元素,是数值, scanf 输入时必须写 &arr[i]
- 二维数组也一样 &arr[i][j];
三、函数知识点
-
函数参数传递
-
值传递:函数内部修改形参,不会影响外面原始变量
-
地址传递(指针):传变量地址,函数内部可以修改外部变量
c
void swap(int *a, int *b) {
// 交换两个数,地址传递
}
- 函数声明 vs 函数定义
- 函数声明:告诉编译器函数存在,写在main前面
int add(int, int); - 函数定义:函数的完整代码实现({}里面逻辑)
规则:如果函数写在main函数后面,main前面必须写函数声明
- 函数返回类型
① void 类型:无返回值
只执行动作,不需要return返回数据
void print_menu(){} //打印菜单
void swap(int *a, int *b){} //交换变量
② 非void类型(int/float/char*):必须return对应类型数据
int is_leap(int year){} //返回1/0,判断闰年
float calculate_area(float r){} //返回面积
char *get_greeting(){} //返回字符串指针
自定义函数和void没有必要的联系,一切一解决问题为导向。
4. 返回值4种用途
-
判断真假: is_leap 返回1是闰年,0不是
-
返回计算结果: add(a,b) 返回a+b
-
操作状态(成功/失败):返回0成功,-1失败
-
返回资源指针: fopen 返回文件指针FILE*
-
递归
函数自己调用自己,必须有终止条件。
适用:阶乘、斐波那契、分治类问题
int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n-1);
}
C语言不支持函数重载(重载是C++特性)
四、算法模板
模板1:二分查找(猜数字,有序序列查找)
核心:不断取中间值,缩小查找区间,前提:数据有序
二分查找5步
- 初始化边界:low左边界,high右边界
- 循环条件 while(low <= high)
- 计算中间值 mid = (low + high)/2
- 比较,缩小区间
- mid > 目标 → high = mid -1
- mid < 目标 → low = mid +1
- mid ==目标 →找到,break退出循环
- 输出结果
第4步就是保证每一次都做有用功
完整代码模板
#include <stdio.h>
int main()
{
int price = 300;
int low = 0;
int high = 1000;
int guess;
while(low <= high)
{
guess = (low + high)/2;
printf(“我猜价格是 %d 元!\n”, guess);
if(guess > price)
{
printf(“高了!\n”);
high = guess - 1;
}
else if(guess < price)
{
printf(“低了!\n”);
low = guess + 1;
}
else
{
printf(“猜对了!价格就是 %d 元!\n”, guess);
break;
}
}
return 0;
}
模板2:双指针动画【两端向中间汇聚字符串】
左指针left从0往右;右指针right从末尾往左,双向填充字符
c
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main()
{
char arr1[] = “welcome to bit!!!”;
char arr2[] = “####################”;
int left = 0;
int right = strlen(arr1)-1;
while(left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf(“%s\n”, arr2);
Sleep(500);
system(“cls”);
left++;
right–;
}
printf(“%s\n”, arr1);
return 0;
}
注意:Linux平台把 Sleep() 换成 usleep() , system(“cls”) 换成 system(“clear”)
五、典型例题代码:奇偶判断(标记变量写法)
c
#include <stdio.h>
int main()
{
int num;
printf(“请输入一个整数:”);
scanf(“%d”, &num);
// 关系表达式赋值给标记变量
int is_even = (num % 2 == 0);
if(is_even == 1)
{
printf(“%d 是偶数。\n”, num);
}
else
{
printf(“%d 是奇数。\n”, num);
}
//简化写法
if(is_even)
{
printf(“简化判断:这是一个偶数。\n”);
}
return 0;
}
六、错题坑点汇总(单独记)
- 数组定义 [] 是容量;访问 arr[i] 中 i 是下标,不要搞混
- = 赋值, ==判断相等 ,if里面极易写错
- 二分查找循环条件是 low <= high ,不是 < ,漏掉等于会漏掉边界值
- 函数定义在main之后,必须写函数声明
- VLA变长数组:定义数组时方括号写变量才是VLA;访问下标用变量不是VLA
- ✅ int arr[10]; arr[i]; 普通访问,C89支持
- ❌ int n; int arr[n]; 变长数组,C99才行
278



被折叠的 条评论
为什么被折叠?



