一.零零碎碎

1.    A、用机器语言编写的源程序就是目标程序
       B、用汇编语言编写的源程序需要经过汇编程序汇编为目标程序
       C、用C语言编写的源程序需要经过编译程序编译为目标程序
       D、C语言与Pascal等其他高级语言的编译器是不一样的

2.    A、一个 C 源程序可由一个或多个函数组成
       B、一个 C 源程序必须包含一个 main 函数
       C、C 程序的基本组成单位是函数
       D、在 C 程序中,自定义函数的定义不能在主函数 main 体内定义

3.”程序存储思想“的提出者是John Von Neumann

4.计算机直接能识别的是二进制的代码

5.   A.计算机存储的都是二进制信息,信息存储的最小单位是二进制位

      B.连续8个位组成的一个字节,是内存的基本度量单位和存储单元 

6.度量单位的转换

1B=8 bits
1KB=1024B=2^10B
1MB=2^10KB=2^20B
1GB=2^10MB=2^20KB=2^30B
1TB=2^10GB=2^20MB=2^30KB=2^40B
1PB=2^10TB=2^20GB=2^30MB=2^40KB=2^50B
1EB=2^10PB=2^20TB=2^30GB =2^40MB=2^50KB =2^60B
1ZB=2^10EB=2^20PB=2^30TB=2^40GB=2^50MB =2^60KB =2^70B
1YB=2^10ZB=2^20EB=2^30PB=2^40TB=2^50GB =2^60MB =2^70KB =2^80B

7.进制

(1)十六进制:1 2 3 4 5 6 7 8 9 A~10 B~11 C~12 D~13 E~14 F~15

(2)进制转换

         A.N进制转十进制:“按权求和 例(101)2 =1*2^2+0*2^1+1*2^0 =5

         B. 十进制转N进制:“除N取余” 记得逆序输出余数

8.    %f是针对float类型的格式符,如果代码中ydouble类型。scanf中读取double类型的浮点数        应该用%lf,如果用%f会导致输入解析错误,y无法正确获取值,从而输出不确定的随机数

9.  A:外部变量(全局变量)作用域是从定义处到整个程序结束,并非 “整个程序”

     B:extern声明外部变量,不是 “重新定义”,定义只能有一次。

     C:全局外部变量可在多个模块使用,extern的作用是声明该变量已在其他模块定义,不是重               新定义

     D:静态外部变量(static修饰的全局变量)作用于本模块,可用于模块内数据隐藏,有实用               价值

10.优先级     char < float < short < int < double

11.C语言开发的4个步骤是:编辑、编译、链接、运(执)行

12.一般情况下,在C语言中定义但未初始化的变量的值为不确定的随机数

13.用scanf输入1个double型变量时,需要使用格式转换说明符 %lf,并且要使用取址运&算符取得该         变量的地址。

14.一个C语言程序由若干个函数组成,其中必须有一个main函数。

15.定义函数时,若缺省函数类型标识符,函数返回值类型为 int

16.书写格式自由,一条语句可以写在多行上

17.运算符不能出现在变量名上

18.
 

二.基本格式

每一行结束时必须加

#include <stdio.h>

int maun()
{

    return 0;
}

三.常量

一、常量的分类及定义

1. 字面常量(直接常量)

直接以字面形式出现的常量,无需声明,直接使用。

(1)整数常量(整型常量)
  • 十进制:由 0-9 组成,不能以 0 开头(除 0 本身)。示例:0123-456
  • 八进制:以0开头,由 0-7 组成。示例:012(对应十进制 10)、077(对应十进制 63)
  • 十六进制:以0x0X开头,由 0-9、a-f(或 A-F)组成。示例:0x1a(对应十进制 26)、0X3F(对应十进制 63)
  • 二进制(C99 及以上支持):以0b0B开头,由 0-1 组成。示例:0b101(对应十进制 5)
(2)实数常量(浮点型常量)

表示带小数的数值,有两种表示形式:

  • 十进制小数形式:由整数部分、小数点、小数部分组成(整数或小数部分可省略,但小数点不能省)。示例:3.140.55.(等价于 5.0)、.6(等价于 0.6)
  • 指数形式:由尾数、eE、指数组成(格式:尾数E指数,表示 “尾数 ×10^ 指数”)。示例:3.14e2(即 3.14×10²=314)、2.5E-3(即 2.5×10⁻³=0.0025)

注意:浮点型常量默认是double类型,若需表示float类型,需在末尾加fF(如3.14f)。

(3)字符常量
  • 普通字符:用单引号''括起来的单个字符。示例:'a''0''+'本质:存储的是字符对应的 ASCII 码值(整数),如'A'的 ASCII 码为 65。
  • 转义字符:以反斜杠\开头,表示特殊含义的字符(无法直接输入的字符)。常用转义字符:
    转义字符含义ASCII 码(十进制)
    \n换行10
    \t水平制表(Tab)9
    \'单引号39
    \"双引号34
    \\反斜杠92
    \0空字符(字符串结束符)0
(4)字符串常量

用双引号""括起来的字符序列(可包含 0 个或多个字符)。示例:"hello""123"""(空字符串)

注意:

  • 字符串常量末尾会自动添加一个\0作为结束标志(计算长度时不包含\0)。
  • 字符常量'a'与字符串常量"a"不同:前者占 1 字节,后者占 2 字节('a' + '\0')。

2. 符号常量(宏定义常量)

#define定义的常量,本质是 “替换”,在预处理阶段会被替换为对应的值。

定义格式:

#define 标识符 常量值  // 末尾无分号

#include <stdio.h>
#define PI 3.14159  // 定义符号常量PI
#define MAX 100     // 定义符号常量MAX

int main() {
    printf("PI = %f\n", PI);  // 预处理后替换为3.14159
    int arr[MAX];  // 替换为int arr[100];
    return 0;
}
特点:
  • 标识符通常用大写字母(区分变量)。
  • 无数据类型,仅做文本替换(可能存在类型隐患)。
  • 作用域从定义处到文件结束(可通过#undef终止作用域)。

3. const 修饰的常量(常变量)

const关键字修饰的变量,其值在定义后不能被修改(具有常量属性)。

定义格式:
const 数据类型 标识符 = 常量值;

#include <stdio.h>

int main() {
    const int a = 10;  // 定义常变量a,值为10
    // a = 20;  // 错误:常变量的值不能修改
    printf("a = %d\n", a);
    return 0;
}
特点:
  • 有明确的数据类型,编译器会进行类型检查。
  • 本质是 “只读变量”,仍占用内存空间(与符号常量的 “替换” 不同)。
  • 作用域与普通变量一致(块级、函数级等)。

二、常量的使用注意事项

  1. 类型匹配:常量的类型需与上下文匹配,例如:

    • 整数常量默认是int类型,超出范围会自动转为long(可加l/L显式指定long,如123L)。
    • 浮点型常量默认是double,若用于float变量需加f(如float x = 3.14f;)。
  2. 符号常量 vs const 常量

    • 符号常量(#define)无类型,仅文本替换,可能导致意想不到的错误(如#define N 2+3N*N会被替换为2+3*2+3)。
    • const常量有类型,更安全,推荐优先使用。
  3. 字符串常量的存储:相同的字符串常量在内存中通常只存储一份(编译器优化),例如:

char* s1 = "abc";
char* s2 = "abc";
// s1和s2指向同一块内存地址

三、总结

常量类型定义方式特点示例
字面常量直接书写无标识符,直接使用1233.14'a'
符号常量#define 标识符 值无类型,预处理替换,作用域到文件结束#define PI 3.14
const 常量const 类型 标识符=值有类型,只读,作用域与变量一致const int MAX=100

四.变量  (遵循 “先定义,后使用” 的原则)

一、变量的定义及初始化

1. 变量的定义

定义变量的本质是向编译器申请一块内存空间,指定其数据类型(决定空间大小和存储格式)和变量名(用于标识该空间)。

定义格式:
数据类型 变量名;
说明:
  • 数据类型:决定变量的存储方式和取值范围(如intfloatchar等,详见 “数据类型补充”)。
  • 变量名:需遵循标识符规则(字母、数字、下划线组成,首字符非数字,区分大小写,不使用关键字)。
示例:
int age;        // 定义int型变量age(存储整数)
float score;    // 定义float型变量score(存储单精度小数)
char gender;    // 定义char型变量gender(存储字符)
批量定义:

同一类型的变量可同时定义,用逗号分隔:

int a, b, c;    // 同时定义3个int型变量a、b、c
float x, y;     // 同时定义2个float型变量x、y

2. 变量的初始化

变量定义时赋予初始值称为 “初始化”(未初始化的变量值为随机值,不可控)。

初始化格式:
数据类型 变量名 = 初始值;  // 定义时直接赋值
示例:
int num = 10;           // int型变量num初始化为10
float pi = 3.14f;       // float型变量pi初始化为3.14(加f表示float类型,否则默认double)
char ch = 'A';          // char型变量ch初始化为字符'A'(本质是ASCII码65)
int x = 5, y = 10;      // 批量定义并初始化
注意:
  • 初始化与赋值的区别:
    • 初始化:仅在定义时执行一次(如int a = 5;)。
    • 赋值:变量定义后修改其值(可多次执行,如a = 10;)。
  • 不同类型的初始值需匹配:
    • 整数不能直接赋值给float(需隐式转换,可能丢失精度),如float f = 10;(合法,但 10 会转为 10.0f)。
    • 字符变量可赋值为字符('A')或 ASCII 码(65),效果相同。

数据类型补充(常用基本类型)

类型关键字占用空间(32 位系统)取值范围(示例)初始化示例
基本整型int4 字节-2147483648 ~ 2147483647int a = 100;
单精度浮点型float4 字节±3.4×10^-38 ~ ±3.4×10^38float f = 3.14f;
双精度浮点型double8 字节±1.7×10^-308 ~ ±1.7×10^308double d = 3.1415926;
字符型char1 字节-128 ~ 127(有符号)char ch = 'B'; 或 66;

二、变量的输入(从键盘读取数据)

变量的输入通过标准库函数scanf()实现,功能是从键盘读取数据并存储到变量中。需包含头文件#include <stdio.h>

1. scanf()函数格式:

scanf("格式控制字符串", &变量1, &变量2, ...);
说明:
  • 格式控制字符串:包含格式占位符(指定输入数据的类型)和普通字符(需原样输入)。
  • &运算符:取变量的内存地址(scanf()需要知道数据存储的位置,普通变量必须加&,数组名除外)。

2. 常用格式占位符

变量类型格式占位符示例
int%dscanf("%d", &a);
float%fscanf("%f", &f);
double%lfscanf("%lf", &d);
char%cscanf("%c", &ch);

3. 输入示例

(1)单个变量输入:
#include <stdio.h>

int main() {
    int age;
    printf("请输入年龄:");  // 提示用户输入
    scanf("%d", &age);      // 读取整数到age
    printf("你输入的年龄是:%d\n", age);
    return 0;
}
(2)多个变量输入:
#include <stdio.h>

int main() {
    float height, weight;
    printf("请输入身高(米)和体重(kg),用空格分隔:");
    // 格式字符串中的空格表示任意空白字符(空格、回车、Tab)
    scanf("%f %f", &height, &weight);  
    printf("身高:%.2f米,体重:%.1fkg\n", height, weight);
    return 0;
}
(3)带普通字符的输入:
#include <stdio.h>

int main() {
    int year, month, day;
    printf("请输入日期(格式:年-月-日):");
    // 格式字符串中的'-'需原样输入
    scanf("%d-%d-%d", &year, &month, &day);  
    printf("你输入的日期是:%d年%d月%d日\n", year, month, day);
    return 0;
}

4. 输入注意事项

  • 类型匹配:输入数据类型必须与格式占位符一致,否则会导致数据错误。例如:用%d读取小数,会只取整数部分(如输入 3.14,变量接收 3)。
  • double的特殊处理double变量必须用%lflong float),若用%f会导致数据错误。
  • 空白字符处理scanf()会自动跳过输入中的空白字符(空格、回车、Tab),但%c除外(会读取空白字符)。例如:输入A B后用%c读取,第一个%c得到'A',第二个%c得到空格(而非'B')。解决方法:在%c前加空格跳过空白,如scanf(" %c", &ch);(格式字符串中的空格会跳过所有空白)。
  • 非占位符的普通字符(如字母、符号)必须被原样输入

三、变量的输出(向屏幕打印数据)

变量的输出通过标准库函数printf()实现,功能是将变量的值按指定格式打印到屏幕。需包含头文件#include <stdio.h>

1. printf()函数格式:

printf("格式控制字符串", 变量1, 变量2, ...);
说明:
  • 格式控制字符串:包含格式占位符(指定输出数据的类型和格式)和普通字符(原样输出)。
  • 变量列表:需输出的变量(无需加&,直接写变量名)。

2. 常用格式占位符及扩展格式

变量类型格式占位符扩展格式(示例)说明
int%d%5d(占 5 位,右对齐)、%-5d(左对齐)控制输出宽度
float/double%f%.2f(保留 2 位小数)、%6.2f(宽 6 位,2 位小数)控制小数位数和总宽度
char%c%c输出字符(按 ASCII 码对应字符)
(通用)%o/%x%o(八进制)、%x(十六进制小写)整数的进制转换输出

3. 输出示例

(1)基本输出:运行
#include <stdio.h>

int main() {
    int a = 100;
    float b = 3.1415f;
    char c = 'Z';
    printf("整数:%d,小数:%f,字符:%c\n", a, b, c);
    // 输出:整数:100,小数:3.141500,字符:Z
    return 0;
}
(2)格式控制(小数位数和宽度):
#include <stdio.h>

int main() {
    double pi = 3.1415926535;
    // %.2f:保留2位小数;%8.2f:总宽度8位(含小数点),右对齐
    printf("pi = %.2f\n", pi);      // 输出:pi = 3.14
    printf("pi = %8.2f\n", pi);     // 输出:pi =    3.14(前面补4个空格)
    return 0;
}
(3)整数进制转换:
#include <stdio.h>

int main() {
    int num = 26;
    printf("十进制:%d\n", num);    // 输出:十进制:26
    printf("八进制:%o\n", num);    // 输出:八进制:32(26的八进制)
    printf("十六进制:%x\n", num);  // 输出:十六进制:1a(26的十六进制)
    return 0;
}

4. 输出注意事项

  • floatdouble的统一printf()%f可同时用于floatdoublefloat会自动转为double)。
  • 格式占位符与变量的对应:数量和类型必须一一对应,否则会输出乱码。例如:printf("%d %f", a);(少一个变量)或printf("%d", b);bfloat类型)都会导致错误。
  • 转义字符的使用:在格式字符串中可加入转义字符(如\n换行、\t制表符)控制输出格式。

四、综合示例(定义、初始化、输入、输出结合)

#include <stdio.h>

int main() {
    // 定义变量并部分初始化
    char name[20];  // 字符数组(用于存储字符串)
    int age;
    float score = 0.0f;  // 初始化成绩为0

    // 输入数据
    printf("请输入姓名:");
    scanf("%s", name);  // 字符串输入无需加&(数组名即地址)
    printf("请输入年龄:");
    scanf("%d", &age);
    printf("请输入成绩:");
    scanf("%f", &score);

    // 输出数据
    printf("\n--- 个人信息 --- \n");
    printf("姓名:%s\n", name);
    printf("年龄:%d岁\n", age);
    printf("成绩:%.1f分\n", score);  // 保留1位小数

    return 0;
}

运行结果示例

请输入姓名:张三
请输入年龄:18
请输入成绩:95.5

--- 个人信息 --- 
姓名:张三
年龄:18岁
成绩:95.5分

五、总结

操作核心函数 / 格式关键注意事项
定义数据类型 变量名;先定义后使用,变量名遵循标识符规则
初始化数据类型 变量名 = 初始值;初始值需与类型匹配,未初始化变量值为随机值
输入scanf("格式", &变量);&(数组除外),double%lf,注意类型匹配
输出printf("格式", 变量);格式占位符与变量一一对应,float/double%f

五.转义字符

C 语言转义字符存储规则表

转义字符类型格式示例存储字节数核心说明
普通转义字符'\n''\t''\\'1 字节单个转义字符(如换行、制表符),本质是对应 ASCII 码值,存储占 1 字节。
八进制转义字符'\141'(对应 'a')1 字节格式为\+1~3 位八进制数字(0-7),表示单个字符,存储占 1 字节。
十六进制转义字符'\x5d'(对应 ']')1 字节格式为\x+1~2 位十六进制数字(0-9、a-f/A-F),表示单个字符,存储占 1 字节。
字符串中的转义字符"\\n""\x41"2 字节字符串常量末尾自动加\0结束符,如"\x41"是字符 'A' + \0,共 2 字节。
空字符转义符'\0'1 字节ASCII 码值为 0,作为字符串结束标志,单独存储占 1 字节。

补充注意事项

  1. 转义字符无论格式多么复杂(如\x7f),只要是 “字符常量”(单引号括起),均只占 1 字节。
  2. 字符串中的转义字符,字节数 = 转义字符实际代表的字符数 + 1(\0结束符),若字符串含多个转义字符,需累加实际字符数(如"\n\t" 是 2 个字符 + \0,共 3 字节)。
  3. 八进制转义字符最多 3 位数字,超出部分按普通字符处理(如'\1234' 中\123是转义字符,4是普通字符)。

六.带修饰符的基本数据类型的汇总表(背)

数据类型(带修饰符)关键字写法占用内存大小(字节)取值范围
字符型
有符号字符型signed char1-128 ~ 127
无符号字符型unsigned char10 ~ 255
短整型
有符号短整型short / short int / signed short / signed short int2-32768 ~ 32767
无符号短整型unsigned short / unsigned short int20 ~ 65535
基本整型
有符号基本整型int / signed / signed int4-2147483648 ~ 2147483647
无符号基本整型unsigned / unsigned int40 ~ 4294967295
长整型
有符号长整型long / long int / signed long / signed long int4-2147483648 ~ 2147483647
无符号长整型unsigned long / unsigned long int40 ~ 4294967295
双长整型(C99)VS2010 支持 long long(C99 特性)
有符号双长整型long long / long long int / signed long long8-9223372036854775808 ~ 9223372036854775807
无符号双长整型unsigned long long / unsigned long long int80 ~ 18446744073709551615
浮点型浮点型无 signed/unsigned 修饰符(默认有符号)
单精度浮点型float4±3.4×10^-38 ~ ±3.4×10^38(约 6~7 位有效数字)
双精度浮点型double8±1.7×10^-308 ~ ±1.7×10^308(约 15~17 位有效数字)
长双精度浮点型long double8(VS2010 中)与 double 相同(±1.7×10^-308 ~ ±1.7×10^308)

七.数据类型

C 语言允许的基本数据类型(核心考点)

  1. 整型(整数类型)

    • 用于存储整数,包括int(基本整型)、short(短整型)、long(长整型)等,支持unsigned(无符号)修饰。
    • 是 C 语言原生支持的基础类型。
  2. 实型(浮点类型)

    • 用于存储带小数的数据,包括float(单精度浮点型)和double(双精度浮点型)。
    • 注意:C 语言中 “实型” 即 “浮点型”,二者等价。
  3. 字符型(char

    • 用于存储单个字符(本质是 ASCII 码值,属于整数类型的一种)。
    • 支持unsigned char(无符号字符型)和signed char(有符号字符型)。
  4. 空类型(void

    • 表示 “无类型”,用于声明无返回值的函数(如void func())、无类型指针(void*)等。
    • 不能用于定义变量(无实际存储意义)。

C 语言基础数据类型表

类型类别具体类型 / 关键字说明
基本类型整型(int等)存储整数,支持符号修饰
基本类型实型(floatdouble存储小数,单 / 双精度之分
基本类型字符型(char存储字符(本质为 ASCII 码整数)
特殊类型空类型(void表示无类型,用于函数返回值或指针
构造类型结构体、数组、枚举等由基本类型组合而成(非基础类型)
指针类型类型*(如int*存储内存地址(派生类型)

八.运算符优先级

1.优先级口诀括号成员最高级,单目算术紧随其后,移位关系按位算,逻辑三目赋值低,逗号运算最低级

一、最高优先级(单目运算符)

运算符含义结合性示例
()圆括号(函数调用)从左到右(a + b) * c
[]数组下标从左到右arr[0]
-> / .结构体成员访问从左到右p->name / s.age
++ / --后缀自增 / 自减(先传递,后加加)从左到右a++ / b--
!逻辑非从右到左!a
~按位取反从右到左~x
+ / -正号 / 负号(单目)从右到左+3 / -5
++ / --前缀自增 / 自减(先++,后传递)从右到左++a / --b
*指针取值从右到左*p
&取地址从右到左&a
sizeof计算类型 / 变量大小从右到左sizeof(int)
(类型)强制类型转换从右到左(float)a

说明:单目运算符仅对一个操作数生效,前缀自增 / 自减的优先级高于后缀(但后缀自增 / 自减的结合性更特殊)。

二、算术运算符(双目)

运算符含义结合性示例
* / / / %乘 / 除 / 取余从左到右a * b / c
+ / -加 / 减(双目)从左到右a + b - c

说明

  • 取余运算符%仅用于整数,结果符号与被除数一致(如5 % 3 = 2-5 % 3 = -2)。
  • 除法/若操作数为整数,结果自动截断小数(如5 / 2 = 2)。

三、移位运算符

运算符含义结合性示例
<<左移从左到右a << 2(左移 2 位)
>>右移从左到右b >> 1(右移 1 位)

说明:移位运算针对二进制位,左移等价于乘以 2 的 n 次方,右移等价于除以 2 的 n 次方(需注意符号位处理)。

四、关系运算符

运算符含义结合性示例
< / > / <= / >=小于 / 大于 / 小于等于 / 大于等于从左到右a < b / c >= d
==等于从左到右a == b
!=不等于从左到右x != y

说明:关系运算结果为整数(1表示真,0表示假),注意==(等于)与=(赋值)的区别。

若同时出现,先算==

五、按位运算符

运算符含义结合性示例
&按位与从左到右a & b
^按位异或从左到右x ^ y
|按位或从左到右m | n

说明:按位运算针对操作数的二进制位逐位计算,仅用于整数类型。

六、逻辑运算符

运算符含义结合性示例
&&逻辑与(短路)从左到右a && b
||逻辑或(短路)从左到右x || y

说明

  • 逻辑与&&:左侧为假时,右侧不再执行。
  • 逻辑或\|\|:左侧为真时,右侧不再执行。

逻辑运算规则

  • 非 0 值视为 “真”(逻辑值为 1),0 视为 “假”(逻辑值为 0)。
  • &&(逻辑与):两边都为真则结果为真(1),否则为假(0)。
  • ||(逻辑或):两边至少一个为真则结果为真(1),否则为假(0)。
  • !(逻辑非):真变假(0),假变真(1)

德摩根定律

     德摩根定律是逻辑运算中的重要规律,适用于两种等价形式: 

  1. !(A && B) 等价于 !A || !B
  2. !(A || B) 等价于 !A && !B

简单来说:“对逻辑与的否定,等价于否定的逻辑或;对逻辑或的否定,等价于否定的逻辑与”

七、条件运算符(三目)

运算符含义结合性示例
?:条件运算从右到左a > b ? a : b

说明:格式为表达式1 ? 表达式2 : 表达式3,若表达式 1 为真则执行表达式 2,否则执行表达式 3,是唯一的三目运算符。(对取左,错取右)

八、赋值运算符

运算符含义结合性示例
=简单赋值从右到左a = b
+= / -=加 / 减后赋值从右到左a += 3(等价于a = a + 3
*= / /= / %=乘 / 除 / 取余后赋值从右到左b *= 2(等价于b = b * 2
<<= / >>=左移 / 右移后赋值从右到左c <<= 1
&= / ^= / |=按位与 / 异或 / 或后赋值从右到左d &= 0x0f

说明:赋值运算符优先级较低,通常最后执行,结合性为从右到左(如a = b = c等价于a = (b = c))。

九、逗号运算符

运算符含义结合性示例
,逗号运算从左到右a = 1, b = 2, a + b

说明:逗号运算符优先级最低,用于分隔多个表达式,整体结果为最后一个表达式的值(如(a=1, b=2, a+b)结果为3)。

九.switch语句

switch 语句是 C 语言中用于多分支选择的流程控制语句,适用于判断条件为整型或字符型表达式的场景,比嵌套 if-else 语句更简洁高效。

一、switch 语句的基本格式

switch (表达式) {
    case 常量表达式1:
        语句块1;
        [break;]
    case 常量表达式2:
        语句块2;
        [break;]
    ...
    case 常量表达式n:
        语句块n;
        [break;]
    default:
        语句块n+1;
        [break;]
}

各部分说明:

  1. 表达式:必须是整型或字符型(包括intcharshortlong及枚举类型等,不能是浮点型、字符串等)。示例:switch (a)switch (ch - '0')(字符转整数)。

  2. case 常量表达式

    • case后必须跟常量表达式(值在编译期可确定,如5'A'3+2,不能是变量或函数调用)。
    • 多个case的常量值不能重复(否则编译报错)。
  3. break 语句

    • 用于跳出当前 switch 结构,若省略,会继续执行后续 case 的语句(称为 “穿透” 现象)。
  4. default 子句

    • 可选,当所有 case 的常量值都不匹配表达式时执行。
    • 位置灵活(可在任意 case 之间或末尾),若在中间,需加 break 避免穿透。

二、执行流程

  1. 计算switch后表达式的值(整型或字符型)。
  2. 依次与各case后的常量表达式比较,找到第一个匹配的值
    • 从该 case 的语句块开始执行。
    • 若遇到break,立即跳出 switch 语句,执行后续代码。
    • 若未遇到break,会继续执行下一个 case 的语句(穿透),直到遇到 break 或 switch 结束。
  3. 若所有 case 都不匹配,且存在default,则执行 default 的语句块;若没有 default,直接跳出 switch。

三、示例解析

示例 1:基本用法(带 break)

#include <stdio.h>

int main() {
    int day = 3;
    switch (day) {
        case 1:
            printf("星期一\n");
            break;
        case 2:
            printf("星期二\n");
            break;
        case 3:
            printf("星期三\n");  // 匹配成功,执行此句
            break;              // 跳出switch
        case 4:
            printf("星期四\n");
            break;
        default:
            printf("其他星期\n");
    }
    return 0;
}

输出星期三(执行流程:表达式day=3匹配case 3,执行打印后 break 跳出。)

示例 2:穿透现象(省略 break)

#include <stdio.h>

int main() {
    char grade = 'B';
    switch (grade) {
        case 'A':
            printf("优秀\n");
        case 'B':
            printf("良好\n");  // 匹配成功,执行此句
        case 'C':
            printf("及格\n");  // 穿透执行
        default:
            printf("加油\n");  // 继续穿透
    }
    return 0;
}

输出

良好
及格
加油

(原因:case 'B'后无 break,导致后续 case 和 default 被依次执行。)

示例 3:利用穿透实现多 case 共享代码

#include <stdio.h>

int main() {
    int month = 2;
    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            printf("31天\n");  // 1/3/5/7/8/10/12月共享此代码
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            printf("30天\n");
            break;
        case 2:
            printf("28或29天\n");
            break;
        default:
            printf("无效月份\n");
    }
    return 0;
}

输出28或29天(多个 case 共用一个语句块,通过穿透实现简洁逻辑。)

四、注意事项

  1. 表达式类型限制

    • 必须是整型或字符型(char本质是整数),不能是浮点型(如3.14)、字符串(如"abc"
    • 错误示例:switch (3.14)(编译报错)、switch ("abc")(编译报错)。
  2. case 常量表达式要求

    • 必须是编译期可确定的常量(如5'A'、宏定义常量#define NUM 10),不能是变量或函数调用
    • 错误示例:case a(a 是变量)、case get_num()(函数调用)。
  3. break 的必要性

    • 若需每个 case 独立执行,必须加break,否则会发生穿透(除非有意利用穿透)。
    • default后建议加break(即使在末尾,养成习惯可避免后续添加 case 时出错)。
  4. case 值的唯一性

    • 多个 case 不能有相同的常量值,否则编译报错(如case 1:case 1:冲突)。
  5. 与 if-else 的选择

    • switch 适合判断条件为离散的整型 / 字符型值(如星期、等级)。
    • if-else 适合范围判断(如x > 10)、浮点型判断等场景,灵活性更高。

五、常见错误案例

错误 1:使用浮点型表达式

float score = 90.5;
switch (score) {  // 错误:表达式不能是浮点型
    case 90: printf("优秀"); break;
    default: printf("其他");
}

错误 2:case 后使用变量

int num = 5;
switch (10) {
    case num: printf("匹配"); break;  // 错误:case后不能是变量
}

错误 3:遗漏 break 导致逻辑错误

int x = 2;
switch (x) {
    case 1: printf("1");
    case 2: printf("2");  // 执行此句
    case 3: printf("3");  // 穿透执行,意外输出3
    break;
}
// 输出:23(而非预期的2)

六、总结

核心要点说明
适用场景多分支选择,条件为整型 / 字符型离散值
执行逻辑匹配 case 后顺序执行,遇 break 则跳出,否则穿透
关键语法表达式为整型 / 字符型,case 后是常量,break 控制分支结束,default 处理默认情况
常见陷阱浮点型表达式、case 用变量、遗漏 break 导致穿透

十.if语句

一、if 语句的三种基本形式

1. 单分支 if 语句(if)

格式

if (表达式) {
    语句块;  // 表达式为真时执行
}

说明

  • 表达式:必须是逻辑表达式或关系表达式(结果为 “真”(非 0)或 “假”(0))。
  • 语句块:若为单条语句,可省略{};多条语句必须用{}包裹(建议始终加{},增强可读性)。

示例

int a = 5;
if (a > 3) {
    printf("a大于3\n");  // a=5>3为真,执行此句
}
// 输出:a大于3

2. 双分支 if 语句(if-else)

格式

if (表达式) {
    语句块1;  // 表达式为真时执行
} else {
    语句块2;  // 表达式为假时执行
}

说明

  • 二选一执行:表达式为真则执行语句块 1,否则执行语句块 2,两者必选其一。

示例

int score = 85;
if (score >= 60) {
    printf("及格\n");  // 85>=60为真,执行此句
} else {
    printf("不及格\n");
}
// 输出:及格

3. 多分支 if 语句(if-else if-else)

格式

if (表达式1) {
    语句块1;  // 表达式1为真时执行
} else if (表达式2) {
    语句块2;  // 表达式1为假、表达式2为真时执行
} else if (表达式3) {
    语句块3;  // 前两个表达式为假、表达式3为真时执行
}
...
else {
    语句块n;  // 所有表达式为假时执行(可选)
}

说明

  • 按顺序判断:从第一个表达式开始,一旦某个表达式为真,执行对应语句块后跳出整个结构;若所有表达式为假,执行 else 语句块(若存在)。
  • else 可选:若省略 else,则所有表达式为假时不执行任何语句块。

示例

int grade = 8;
if (grade >= 9) {
    printf("优秀\n");
} else if (grade >= 7) {
    printf("良好\n");  // 8>=7为真,执行此句
} else if (grade >= 6) {
    printf("及格\n");
} else {
    printf("不及格\n");
}
// 输出:良好

二、if 语句的嵌套

if 语句内部可以包含另一个 if 语句(单分支、双分支或多分支),称为嵌套 if 语句,用于处理更复杂的条件判断。

格式示例

if (表达式1) {
    if (表达式2) {
        语句块1;  // 表达式1和表达式2均为真时执行
    } else {
        语句块2;  // 表达式1为真、表达式2为假时执行
    }
} else {
    语句块3;  // 表达式1为假时执行
}

示例:判断一个数是否为正偶数

int num = 4;
if (num > 0) {  // 先判断是否为正数
    if (num % 2 == 0) {  // 再判断是否为偶数
        printf("正偶数\n");  // 4>0且4%2==0,执行此句
    } else {
        printf("正奇数\n");
    }
} else {
    printf("非正数\n");
}
// 输出:正偶数

注意:嵌套时建议使用{}明确语句块范围,避免因缩进错误导致逻辑混乱(C 语言不依赖缩进判断结构)。

三、关键注意事项

1. 表达式的真假判断

  • C 语言中,“真” 指表达式值为非 0(包括正数、负数、字符常量等),“假” 指表达式值为0
  • 示例:
    if (5) { ... }  // 5为非0,视为真
    if (-3) { ... }  // -3为非0,视为真
    if ('a') { ... }  // 'a'的ASCII码为97(非0),视为真
    if (0) { ... }  // 0为假,不执行
    

2. 悬空 else 问题

else 始终与最近的未配对 if结合,与缩进无关,可能导致逻辑错误。

反例

int a = 1, b = 0;
if (a == 0)
    if (b == 0)
        printf("a=0且b=0\n");
else  // 实际与内层if配对,而非外层if
    printf("a≠0\n");
// 预期:a≠0时输出,但实际因外层if为假,不执行任何语句

解决方法:加{}明确配对关系

int a = 1, b = 0;
if (a == 0) {
    if (b == 0)
        printf("a=0且b=0\n");
} else {  // 明确与外层if配对
    printf("a≠0\n");  // 执行此句
}
// 输出:a≠0

3. 赋值运算符与等于运算符的区别

  • =是赋值运算符,==是等于运算符,在 if 表达式中易混淆。
  • 错误示例:if (a = 5) 实际是将 5 赋值给 a,表达式值为 5(真),导致逻辑错误。
  • 正确写法:if (a == 5) (判断 a 是否等于 5)。

4. 表达式的简化

  • 逻辑表达式可简化,例如:
    • if (a != 0) 可简化为 if (a)(非 0 即真)。
    • if (a == 0) 可简化为 if (!a)(0 的非为真)。

四、if 语句与 switch 语句的对比

特性if 语句switch 语句
适用场景范围判断(如x > 10)、任意类型表达式离散值判断(如整数、字符)
条件类型可处理浮点型、逻辑表达式等仅支持整型或字符型表达式
灵活性更高,可嵌套复杂逻辑较低,仅匹配常量值
代码简洁性多分支时嵌套多,代码冗长多分支时更简洁,避免嵌套

选择建议

  • 简单范围判断或少量分支 → 用 if 语句。
  • 多分支且条件为离散整型 / 字符型 → 用 switch 语句

更多推荐