C语言学习笔记——其一
该笔记持续更新,如有错误请在评论区指正,谢谢🙏
常量和变量
常量是在程序运行过程中 值不能改变 的数据;变量是在程序运行过程中 值可以改变 的存储空间。
- 初始化变量:
<类型名称> <变量名称> = <初始值>
- 类型名称:告诉编译器,这个变量可以存储什么类型的数据。
- 例如:
int
表示整数,float
表示单精度浮点数,char
表示字符等。
- 例如:
- 变量名称:是程序中引用这个数据的“名字”,方便我们后续使用。
- 定义变量的过程会为它 分配内存空间。
📌 示例:
int age = 18; // 定义(声明)变量 age 并赋值 18
数据类型
整数数据类型
类型 | 大小(字节)* | 取值范围(典型 32 位系统) | 说明 |
---|---|---|---|
short / short int | 2 | -32,768 ~ 32,767 | 短整型 |
unsigned short | 2 | 0 ~ 65,535 | 无符号短整型 |
int | 4 | -2,147,483,648 ~ 2,147,483,647 | 默认整型 |
unsigned int | 4 | 0 ~ 4,294,967,295 | 无符号整型 |
long / long int | 4(Win) / 8(Linux 64 位) | 取决于系统 | 长整型 |
unsigned long | 同上 | 同上 | 无符号长整型 |
long long | 8 | 约 ±9×10¹⁸ | 长长整型 |
unsigned long long | 8 | 0 ~ 1.8×10¹⁹ | 无符号长长整型 |
short int
=short
,int
可忽略- 使用
unsigned int
类型赋值时,输出时的整数占位符需要改为%u
- 使用
long
类型赋值时,初始值后需要加L
,输出时的整数占位符需要改为%ld
- 使用
long long
类型赋值时,初始值后需要加LL
,输出时的整数占位符需要改为%lld
小数数据类型(浮点型)
类型 | 大小(字节) | 有效数字位数 | 范围(约) | 说明 |
---|---|---|---|---|
float | 4 | 6~7 位 | 3.4E-38 ~ 3.4E38 | 单精度浮点数 |
double | 8 | 15~16 位 | 1.7E-308 ~ 1.7E308 | 双精度浮点数 |
long double | 10/12/16(取决于编译器) | >16 位 | 范围更大 | 扩展精度浮点数 |
浮点数的范围与精度
- printf输出inf表示超过范围的浮点数:+∞
- printf输出nan表示不存在的浮点数
字符类型
类型 | 大小(字节) | 取值范围 | 说明 |
---|---|---|---|
char | 1 | -128 ~ 127(signed)或 0 ~ 255(unsigned) | 存储单个字符(ASCII 码) |
signed char | 1 | -128 ~ 127 | 有符号字符 |
unsigned char | 1 | 0 ~ 255 | 无符号字符 |
定义一个长度为 4 的 char
数组,名为 str
:
char str[4] = "aaa"
// 4为字节(aaa+\0)
// C 语言在字符串末尾会自动添加一个 \0(空字符) 作为结束标志。
char str[999];
scanf("%s"),&str);// 键盘录入
printf("录入%s",str);
sizeof测量某种类型的大小
sizeof可以用来测量数据类型或变量在内存中占用的字节数。
sizeof(数据类型)
sizeof(变量名)
sizeof(数据类型)
→ 直接测量某种类型的大小sizeof(变量名)
→ 测量某个变量的大小(根据变量的类型决定)
示例
#include <stdio.h>
int main() {
printf("int 占用 %zu 字节\n", sizeof(int));
printf("double 占用 %zu 字节\n", sizeof(double));
char c = 'A';
printf("变量 c 占用 %zu 字节\n", sizeof(c));
int arr[10];
printf("数组 arr 占用 %zu 字节\n", sizeof(arr)); // 整个数组的字节数
printf("arr[0] 占用 %zu 字节\n", sizeof(arr[0])); // 单个元素的字节数
return 0;
}
转义字符
转义字符(escape character) 是以反斜杠 \
开头的特殊字符序列,用来表示一些无法直接输入或具有特殊意义的字符。
转义字符 | 含义 | 示例 |
---|---|---|
\n | 换行(newline) | printf("Hello\nWorld"); → 输出两行 |
\t | 水平制表符(tab) | printf("A\tB"); → A 和 B 之间有一个制表空格 |
\ | 反斜杠本身 | printf("\"); → 输出 \ |
' | 单引号 | printf("'"); → 输出 ' |
" | 双引号 | printf("""); → 输出 " |
\0 | 空字符(字符串结尾标志) | "abc\0def" 只会输出 abc |
\r | 回车(carriage return) | 光标移动到行首 |
\b | 退格(backspace) | 光标回退一格 |
\xhh | 十六进制 ASCII 码 | \x41 → A |
\ooo | 八进制 ASCII 码 | \101 → A |
类型转换
- 隐式类型转换(自动转换):低精度 → 高精度
- 显式类型转换(强制类型转换 ):
(新类型) 表达式
double pi = 3.14;
int x = (int)pi; // x = 3,小数部分被截断
char ch = (char)97; // ch = 'a'
赋值计算
加减乘除计算
// 加减计算
int a;
int b;
scanf("%d %d",&a,&b);
printf("%d",a+b);
注:
- 整数计算的结果一定是整数
- 小数直接参与计算结果可能不准确
- 取余的数据必须都是整数
- 取余的正负是跟第一个数字保持一致的
- 单目(+/-)优先级高于乘除
- 强制类型转换的优先级高于四则运算
printf("%d\n",2 + 1); // 3
printf("%d\n",10 / 3); // 3
printf("%d\n",-10 / 3); // -1

image.png
复合赋值
- 5个算术运算符:“
+=
,-=
,*=
,/=
”
total += 5; // total = total+5
total *= sum + 12 // total = total*(sum+12)
- 递增递减运算符:“++,—” (变量+1 / -1)
- a++和a—都可以
- a++是a+1以前的值,也就是说a++的值是10+1=11之前的a值,等于10,那么此时a=11,而++a这一步是说a此时值已经是11了,但++a的值是直接等于a+1运算之后的结果,所以a=12
#include <stdio.h>
int main()
{
int a;
a = 10;
printf("a++=%d\n", a++);
printf("a=%d\n", a);
printf("++a=%d\n", ++a);
printf("a=%d\n", a);
return 0;
}
a++=10 // 后缀自增:先用 10,再变 11
a=11
++a=12 // 前缀自增:先变 12,再用 12
a=12
逻辑运算
运算符 | 名称 | 功能说明 |
---|---|---|
&& | 逻辑与(AND) | 两个操作数都为真时,结果才为真 |
! | 逻辑非(NOT) | 对操作数取反,真变假,假变真 |
|| | 逻辑或 |
- 表达$a∈(4,6)$ ➡️
a>4 && a<6
- 判断是否为大写字母:
c≥’A’ && c≤’Z’
- 优先级:
!
>&&
>||
逻辑运算自左向右,若左边不成立,直接短路,右边的也不会执行,例如
a==6 && b+=1
条件运算和逗号运算
如果条件为真,则1,否则2
条件表达式 ? 表达式1 : 表达式2
表达式1, 表达式2, 表达式3
表达式1, 表达式2, 表达式3
if语句
if (im < 0) {
im = 60 + im;
ih --;
}
关系语句
关系运算符 | 意义 | |
---|---|---|
== | 相等 | |
! = | 不相等 | |
>/≥/</≤ | 大于/大于或等于/小于/小于或等于 |
关系运算的结果:符合预期为整数1,反之为0
printf("%d",5==3); // 0
printf("%d",5!=3); // 1
所有关系运算符的优先级比算术运算符低,但是比赋值运算高
printf("%d",7 >=3+4); // 1
但! =和==的优先级较其他关系运算符低
6 > 5 > 4 // 0
/*6>5 变成了 1 ,1 > 4不成立,结果为0*/
else
找零程序
// 初始化变量
int price = 0;
int bill = 0;
// 提示输入并获取数据
printf("请输入金额: ");
scanf("%d", &price);
printf("请输入票面: ");
scanf("%d", &bill);
// 计较零
if (bill >= price) {
printf("应该找您: %d\n", bill - price);
} else {
printf("您的钱不够\n");
}
if (diff < 0) diff += 24 * 60; // = if (diff < 0) { ...}
级联的if-else
分段函数
int main()
{
int x = 2;
int f;
if (x < 0) {
f = -1;
} else if (x == 0) {
f = 0;
} else {
f = 2 * x;
};
printf("f is %d",f);
return 0;
}
switch-case语句
switch (表达式) {
case 常量1:
// 代码块1
break;
case 常量2:
// 代码块2
break;
default:
// 可选,处理其他情况
break;
}
- switch语句可以看作是一种基于计算的跳转,计算控制表达式的值后,程序会跳转到相匹配的casee(分支标号)处。分支标号只是说明switch内部位置的路标,在执行完分支中的最后一条语句后如果后面没有break,就会顺序执行到下面的case里去,直到遇到一个break,或 者switch结束为止
- 表达式:通常是一个整型或枚举类型的值
示例输出:Wednesday
#include <stdio.h>
int main() {
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
default:
printf("Other day\n");
break;
}
return 0;
}
循环
while
循环
- 计算数字位数程序
int x;
int n=0;
scanf("%d",&x);
n++;
x /=10;
while (x > 0)
{
n++;
x /=10;
}
printf("%d\n",n);
do-while
循环
- 先执行一次循环体,再判断条件
#include <stdio.h>
int main()
{
int x;
int n = 0;
scanf("%d", &x);
do {
n++;
x /= 10;
} while (x > 0);
printf("%d\n", n);
return 0;
}
猜数游戏
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(time(0)); // 用当前时间初始化随机数种子
int number = rand() % 100 + 1; // 生成 1~100 的随机整数
int count = 0; // 猜测次数
int a = 0; // 玩家输入的数字
printf("我已经想好了一个1到100之间的数。\n");
do {
printf("请猜这个1到100之间的数:");
scanf("%d", &a);
count++;
if (a > number) {
printf("你猜的数大了。\n");
} else if (a < number) {
printf("你猜的数小了。\n");
}
} while (a != number);
printf("太好了,你用了%d次就猜到了答案。\n", count);
return 0;
}
算平均数
- 读取一组整数,遇到
-1
时停止输入,并计算这些数的平均值。
c #include <stdio.h> int main() { int number; // 用于存储当前输入的数 int sum = 0; // 所有输入数的累加和 int count = 0; // 已输入的数字个数 scanf("%d", &number); // 先读入一个数字 while ( number != -1 ) { // 当输入的不是 -1 时循环继续 sum += number; // 把当前数字加到 sum count ++; // 计数器加 1 scanf("%d", &number); // 再读取下一个数字 } printf("%f\n", 1.0*sum/count); return 0; }
整数求逆
一个整数的分解:
- 对一个整数%10,求出它的个位数
- 再对这个整数/10,将它的个位数丢掉
- 对步骤2后的数再%10,求出新的数的个位
#include <stdio.h>
int main()
{
int x;
scanf("%d",&x);
int digit;
int ret = 0;
while (x > 0) {
digit = x%10;12
ret = ret*10 + digit;
printf("x=%d,digit=%d,ret=%d\n",x,digit,ret);
x/=10;
}
printf("%d",ret);
return 0;
}
for
循环
- 用
while
循环做阶乘
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact = 1;
int i = 1;
while (i<=n) {
fact *= i;
i++;
}
printf("%d!=%d\n",n,fact);
return 0;
}
- 使用
for
循环做阶乘
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact = 1;
int i = 1;
for ( i=1; i<=n; i++) {
fact *= i;
}
printf("%d!=%d\n",n,fact);
return 0;
}
// 因为编译器原因,i+1可以改为int 1 =1并把上句的i初始化删去
i=1
为初始化表达式,i<=n
为条件表达式(循环继续的条件),i++
为更新表达式(循环每轮要做的事情),{}
里为循环体语句;
for (初始化表达式; 条件表达式; 更新表达式) {
循环体语句;
}
- for循环执行流程:
- 执行初始化表达式。
- 判断条件表达式,为真 → 执行循环体。
- 执行更新表达式。
- 重复步骤 2~3,直到条件为假。
🔹 小技巧:
for
的三个部分可以省略,但分号不能省,例如for(;;)
是死循环。for
循环常用来遍历数组、执行计数任务等。- 如果有固定次数,用
for
;必须执行一次,用do-while
;其他用while
循环控制
使用continent
和break
来控制循环

image.png
素数的判断和输出
- 素数的判断
#include <stdio.h>
int main()
{
int x;
scanf("%d",&x);
int i;
int isPrime = 1; //isPrime为1的时候是素数,为0的时候不是素数
for (i=2;i<x;i++) {
if (x%i == 0) {
isPrime = 0;
break; //break跳出循环
}
}
if (isPrime == 1) {
printf("是素数\n");
} else {
printf("不是素数\n");
}
return 0;
}
- 使用嵌套循环输出100以内的素数
#include <stdio.h>
int main()
{
int x;
for (x=2;x<100;x++)
{
int i;
int isPrime = 1; //isPrime为1的时候是素数,为0的时候不是素数
for (i=2;i<x;i++) {
if (x%i == 0) {
isPrime = 0;
break; //break跳出循环
}
}
if (isPrime == 1) {
printf("%d\n",x);
}
}
return 0;
}