记忆(全是原题)

题型分布

一、选择题(共20小题,每小题1分,共20分)

二、填空题(共10空,每空1分,共10分)

三、判断题(共10小题,每小题1分,共10分)

四、程序阅读题(共5小题,每小题4分,共20分)

五、算法设计题(共2小题,每小题8分,共16分)

六、程序设计题(共2小题,每小题12分,共24分)

一、选择题(共20小题,每小题1分,共20分)

1、考察格式化输出与 ASCII 码

题目:已知字符 a 的 ASCII 码为 97,执行语句 printf("%c%d", 'b', 'b'+1); 后输出结果是________

A、b99 B、98c C、9899 D、bc

  • 解析
    • 'b' 的 ASCII 码是 98(因为 'a' 是 97,'b' 紧随其后)。
    • 第一个格式符 %c 对应参数 'b':输出字符形式 b
    • 第二个格式符 %d 对应参数 'b'+1:即 98 + 1 = 99%d 要求输出整数形式,所以输出 99
    • 拼接起来就是 b99

2、考察 if 语句的作用范围与逗号表达式

题目:定义 int x=4,y=3,z=5;,下列四个程序段中有 3 个程序段的执行结果相同,另一个执行结果不同的是________

A、if(x>y) z=x,x=y,y=z;

B、if(x>y) { z=x,x=y,y=z;}

C、if(x>y) z=x;x=y;y=z;

D、if(x>y) {z=x;x=y;y=z;}

  • 解析
    • x > y4 > 3,条件为真。
    • A: if(x>y) z=x,x=y,y=z; —— 逗号表达式 z=x,x=y,y=z 被视为一条语句。因为条件为真,这三个赋值都会执行。
    • B: if(x>y) { z=x,x=y,y=z;} —— 花括号内包含一条逗号表达式语句,效果同 A,全部执行。
    • D: if(x>y) {z=x;x=y;y=z;} —— 花括号内包含三条独立语句,因为有花括号包裹,全部受 if 控制,全部执行。
    • C: if(x>y) z=x; x=y; y=z; —— 陷阱! if 只能控制紧跟其后的第一条语句(即 z=x;)。后面的 x=y;y=z;if 无关,无论条件真假都会执行。
    • 虽然在本题具体数值下,条件为真,看起来大家都执行了。但从程序逻辑结构来看,C 的控制范围与其他三项不同(如果 x>y 为假,A/B/D 什么都不做,而 C 依然会执行后两句赋值)。
变量不为0 就是true
int n;

if (n) {

		……

}

区分赋值和判等
int x;

if (x=1) {

		……

}
if (x==1) {

		……

}

注意区分 看准括号和分号的位置
if (条件) {

	a = 1;

	b = 2;

}

if (条件)

	a = 1;

b = 2;

if (条件)

	a = 1, b =2;

if (条件);
a = 1;

b = 2;

3、考察do-while 循环

题目:程序段 int n=3; do{ printf("%d",n--);}while(!n); 的执行结果是________

A、3 2 1 B、死循环 C、2 D、3

  • 解析
    1. 第一次执行循环体:打印 n (3),然后 n 自减变为 2。
    2. 判断条件while(!n)while(!2)。在 C 语言中,2 是真,!2 就是假 (0)。
    3. 结果:条件为假,循环终止。
    4. 所以屏幕上只输出了一个 3

4、考察无符号数

题目:设 int i,a=1; unsigned j;,则下列语句执行会出现无限循环的语句是________

A、for(j=15;j>0;j-=2) a++;

B、for(j=0;j>15;j+=2) a++;

C、for(i=0;i>15;i+=2) a++;

D、for(i=15;i>0;i-=2) a++;

  • 解析
    • A: for(j=15; j>0; j-=2)。注意 junsigned (无符号整数)
      • 序列变化:15, 13, ..., 3, 1。
      • 下一步:1 - 2。在数学上是 -1,但在计算机无符号数运算中,它会变成一个巨大的正整数(通常是 2^32 - 1)。
      • 结果:这个巨大的数依然 > 0,循环条件永远成立,导致死循环。
    • B/C: 初始条件 0 > 15 不成立,一次都不执行。
    • D: iint (有符号)。1 - 2 变成 -1-1 > 0 为假,循环正常结束。

5、考察循环语句的特性

题目:下列关于循环语句 for、while、do-while 的叙述中正确的是________

A、三种循环语句都可能出现无穷循环

B、三种循环语句中都可以缺省循环终止条件表达式

C、三种循环语句的循环体都至少被无条件地执行一次

D、三种循环语句的循环体都必须放入一对花括号中

  • 解析
    • A: 正确。只要条件设置不当(如 while(1)),三种循环都可能死循环。
    • B: 错误。for(;;) 可以缺省条件,但 while()do-while() 的括号内必须有表达式(哪怕是常数 1)。
    • C: 错误。forwhile 是“先判断后执行”,可能一次都不执行。只有 do-while 至少执行一次。
    • D: 错误。如果循环体只有一条语句,花括号 {} 可以省略。

6、考察函数形参(数组)声明

题目:下列关于函数形参的声明中正确的是________

A、int a[][]

B、int a[]

C、int a[]={0}

D、int a[2][]

  • 解析
    • B: int a[] —— 正确。作为函数参数时,一维数组可以不写长度(本质是退化为指针 int *a)。
    • A/D: int a[][]int a[2][] —— 错误。多维数组作为参数,第一维可以省略,但后面的维度必须写明(例如 int a[][5] 是对的)。编译器需要知道列宽来计算地址。
    • C: int a[]={0} —— 错误。函数形参只是声明,不能在参数列表中进行初始化赋值

7、考察文件

题目:下列函数中,可以把整型数据以二进制形式写入文件中的函数是________

A、fputc() B、fwrite()

C、fread() D、fgetc()

  • 解析
    • B: fwrite() —— 专门用于二进制块读写的函数。
    • A: fputc() —— 写入单个字符(文本模式)。
    • C/D: fread() / fgetc() —— 都是读取函数,不是写入。

8、考察文件

题目:当文件被正常关闭时,fclose()函数的返回值是________

A、-1

B、true

C、0

D、1

  • 解析
    • fclose 关闭成功返回 0
    • 关闭失败返回 EOF(通常定义为 -1)。

9、考察宏定义

题目:在宏定义语句 #define PI 3.1415926 中,宏名 PI 的是________

A、一个字符串

B、一个单精度数

C、一个常量

D、一个双精度数

  • 解析
    • 在 C 语言术语中,用 #define 定义的标识符被称为符号常量(Symbolic Constant)。
    • 它不是字符串(没有双引号),也不是变量。虽然它代表一个双精度数,但“符号常量”是更准确的定义分类。
image-ac0a0a00

10、考察宏替换

题目:设有定义 #define d 2 等,以下表达式中有语法错误的是_______

A、x++

B、y++

C、c++

D、d++

  • 解析
    • 宏定义是纯文本替换。预处理阶段会将代码中所有的 d 替换为 2
    • A: x++ -> 5++(变量自增,正确)。
    • B: y++ -> 3.83++(变量自增,正确)。
    • C: c++ -> c 是变量,可以自增。
    • D: d++ -> 被替换为 2++
      • 错误原因:自增运算符 ++ 只能用于变量(左值),不能用于常量或表达式。你不能强迫数字 2 变成 3。
image-30abfe31

注:上面的内容是原题,接下来的内容为推测必考点:

11、考察标识符

image-617c0155

12、考察数组

在C语言中,数组下标是从( )开始的。

A. 0 B. 1 C. 2 D. 任意整数

若有定义 int arr[5];,则数组arr的最后一个元素是( )。

A. arr[0] B. arr[4] C. arr[5] D. arr[6]

以下关于二维数组的描述,正确的是( )

A. 二维数组在内存中是按列存储的

B. 二维数组可以看作是一维数组的数组

C. 二维数组的行数和列数必须在编译时确定

D. 二维数组的所有元素必须具有相同的值

13、考察函数

Q1:什么是形参,什么是实参?

  • 形参 (Formal Parameter):
    • 定义时括号里的变量。
    • 它是“占位符”,函数未被调用时不占内存,只有调用时才分配内存。
    • 例子: void fun(int a) 里的 a
  • 实参 (Actual Parameter):
    • 调用时括号里传递的具体数值或变量。
    • 它是“实际的数据”,必须有确定的值。
    • 例子: fun(2) 里的 2
  • 关系: 发生函数调用时,实参的值会单向复制给形参(值传递)。

Q2:函数调用之前是否需要先声明?

  • 原则上需要。 编译器必须先认识这个函数(知道它的名字、参数类型、返回值类型),才能检查调用是否合法。
  • 特例: 如果函数的定义(完整代码)写在调用它的位置之前,那么定义本身就充当了声明,不需要额外写声明语句。

Q3:是否可以调用 main 函数?

  • 在 C 语言中:可以。 main 函数本质上也是一个函数,可以在程序中递归调用自己(虽然在实际开发中极少这样做,容易死循环)。
  • (注:在 C++ 中是禁止调用 main 函数的,但 C 语言考试通常认为可以)

Q4:什么是外部函数和内部函数,分别使用哪个关键字?

  • 内部函数 (静态函数):
    • 只能被当前文件中的其他函数调用,不能被其他文件使用。
    • 关键字:static
    • 格式:static int fun(...)
  • 外部函数:
    • 可以被其他文件调用。C 语言中函数默认都是外部的。
    • 关键字:extern (定义时通常省略,声明时可加上)

Q5:当哪条语句被执行时,程序的执行流程无条件地从一个函数跳转到另一个函数?

  • 答案:函数调用语句
    • 当程序执行到 fun(); 这种调用语句时,控制权会立即从当前函数(如 main)转移到被调用的函数(如 fun)。
    • return 语句则是将控制权跳回

14、考察自增自减

int a=5;
int b,c;
b=++a;
c=a++;

a, b, c的值最终是多少?
++a  a=6
b=a=6
c=a=6
a++ a=7

a=7 b=6 c=6

15、考察printf

printf函数调用时,格式说明符数量与实际提供的参数数量不一致时会发生什么?

printf("%d", a, b);   // 只输出 a,b 被忽略

具体来说
1. 格式说明符多于参数
int a = 10;
printf("%d %d", a);

%d 有两个,但只提供了一个参数
第二个 %d 没有对应参数

结果:
输出第一个数字正确(10)
第二个数字随机、可能乱码、甚至导致段错误
本质原因:printf 依赖栈访问参数,如果没提供就读取随机栈值

2. 格式说明符少于参数
int a = 10, b = 20;
printf("%d", a, b);

%d 只有一个说明符,但提供了两个参数

结果:
只使用第一个参数 a
b 被忽略
不会报错,也不会打印 b

3. 参数类型与格式符不匹配
double x = 3.14;
printf("%d", x);

%d 期望 int,实际传入 double

结果:
输出不可预测
可能出现乱码或错误值
这是 典型未定义行为(Undefined Behavior)

16、考察格式化输出

格式修饰符都有哪些?
%d, %3d, %u, %x, %#x, %ld, %f, %lf, %4.2f, %c, %s的含义分别是什么?
printf(“%c,%d”, ‘A’,’A’);
%d
	含义:输出十进制有符号整数(int)

%3d
	含义:输出宽度至少为 3 的十进制整数,右对齐
	若数字不足 3 位,左边补空格
	若超过 3 位,直接原样输出

%u
	含义:输出无符号十进制整数(unsigned int)
	同一块内存,按“无符号”方式解释

%x
	含义:以十六进制输出整数(小写字母 a–f)
	仅影响显示,不改变变量的值

%#x
	含义:以十六进制输出,并自动加前缀 0x
	字母仍为小写

%ld
	含义:输出 long int 类型的十进制整数
	用于 long 型整数

%f
	含义:输出浮点数(float / double)
	默认 保留 6 位小数

%lf
	含义:
		printf 中:等价于 %f
		scanf 中:表示读入 double

%4.2f
	含义:
		总宽度至少为 4
		小数点后保留 2 位
		默认右对齐

%c
	含义:输出一个字符
	对应 char 类型或字符常量

%s
	含义:输出字符串(以 \0 结尾的字符数组)
	不输出 \0

printf("%c,%d", 'A', 'A');
%c
'A' 作为字符输出
输出字符:A

%d
'A' 实际是字符常量
在 C 语言中,字符本质是整数(ASCII 码)
'A' 的 ASCII 值是 65

实际输出结果:
A,65

17、考察数学库

要调用数学函数时,在#include命令行应该包含 math.h

18、考察表达式运算结果

问题:int k = a > b;
	   k =
a>b -> true -> 1
k=1a>b -> false -> 0
k=0

19、考察switch case

image-c37af5b2 image-bd62b477

20、考察字符串比较函数strcmp()

如何通过strcmp函数比较两个字符串?
strcmp 函数定义在 <string.h> 头文件中,用于 比较两个字符串。

函数原型:
int strcmp(const char *str1, const char *str2);

返回值说明:
返回 0:两个字符串 完全相同
返回 < 0:str1 小于 str2(按 ASCII 码顺序比较)
返回 > 0:str1 大于 str2(按 ASCII 码顺序比较)

注意:strcmp 是区分大小写的。例如 "abc""ABC" 不相等。
image-fae0ef71 image-2e6d0882 image-03e82a37

二、填空题(共10空,每空1分,共10分)

1、考察三目运算符

题目:若定义 int a=5; 则表达式 (a>0 ? a : -a) 的值为 5

考点

  • 语法表达式1 ? 表达式2 : 表达式3
  • 解析
    1. 先判断 表达式1 (即 a>0) 是否为真。
    2. 因为 a=5,所以 5>0 成立(为真)。
    3. 表达式2 (即 a) 的值作为整个表达式的结果。
    4. 如果是假,则取 表达式3 (-a)。
    • 注:这其实就是求绝对值的逻辑。

2、考察输入输出

题目:scanf()函数的输入项必须是 地址 ,不能是变量名。

考点

  • scanf 原理scanf 需要修改变量的值,在 C 语言中,要修改一个变量,必须知道它在内存中的位置。
  • 解析
    • 错误写法:scanf("%d", a); (只传了值,scanf 找不到屋子在哪,没法把东西放进去)。
    • 正确写法:scanf("%d", &a);& 取地址符,告诉 scanf 变量 a 的门牌号)。
    • 特例:如果是字符数组(字符串) char str[10], 写 scanf("%s", str) 是对的,因为数组名本身就是地址。

3、考察字符输入输出

题目:getchar()和putchar()函数只能用于 单个 字符的输入和输出。

考点

  • 函数功能差异
    • printf/scanf:格式化,可以处理各种类型,可以处理多个。
    • puts/gets:专门处理字符串(一串字符)。
    • putchar/getchar:专门处理单个字符 (char)。
  • 解析getchar 一次只读一个字,putchar 一次只打一个字。

4、考察逻辑运算与算术运算

题目:若定义“int m=23,n=5;”,则表达式 !m+m%n 的值是 3

考点

  • 运算符优先级! (逻辑非) > % (取余) > + (加法)。
  • 逻辑值的数值化:真为 1,假为 0。
  • 解析
    1. 先算 !mm 是 23 (非 0 即为真)。对“真”取反就是“假”。在 C 语言中,假的值是 0。所以 !m 变成了 0
    2. 再算 m%n23 除以 5,商 4 余 3。所以 m%n3
    3. 最后算加法0 + 3 = 3

5、考察结构体

题目:结构体的每个成员的数据类型可以是基本数据类型,也可以是 构造 类型。

考点

  • 数据类型分类
    • 基本类型:int, float, char 等。
    • 构造类型:数组、结构体 (struct)、共用体 (union)。
  • 解析:结构体里可以套娃。比如“学生”结构体里,可以有一个成员是“生日”,而“生日”本身又是一个包含年月日的小结构体。

6、考察sizeof

题目:使用sizeof()函数计算结构体List的长度的表达式是 sizeof(struct List)

考点

  • sizeof 用法sizeof 是运算符,不是函数(虽然长得像)。
  • 语法sizeof(类型名)sizeof(变量名)
  • 解析
    • 题目说“结构体 List”,通常指的是 struct List { ... };
    • 在 C 语言中,引用这个类型时必须带上 struct 关键字,即 struct List
    • 所以计算大小时写 sizeof(struct List)

注:上面的内容是原题,接下来的内容为推测必考点:

7、考察基础知识

C语言中, 语句 是程序最基本的执行单位,以分号结尾。

8、考察基础知识

字符(char)是 1,短整(short)是 2。 整型(int)、单浮点(float) 都是 4。 双浮点(double) 是 8

9、考察字符数组

以下代码段的输出结果是 China

char ch[20] = {"China\0Beijing"};

printf("%s", ch);

sizeof(“hello”)=?
6
末尾有\0

10、考察逻辑运算符和逻辑表达式

int x=33,y=4;
!x+x/y=?
!330
0 + x / y
33 / 48
0 + 8
0 + 8 = 8

结果为 8

三、判断题(共10小题,每小题1分,共10分)

注:这部分没明确暗示,把一些没归类好的但90%考的整理进来:

switch语句中,各个case和default的出现次序影响执行结果吗? 不影响

long long 占8字节 使用%lld格式化输出

unsigned long long 使用%ull格式化输出

任何程序的结构都可以通过3种基本结构进行组合来实现,分别是 顺序结构选择结构循环结构

c语言本身提供输入输出语句吗? C 语言的“语言本身”不提供输入输出语句;输入输出是由标准库提供的。

  • C 语言核心语法(如变量、表达式、控制结构、函数定义等)中没有内建的 I/O 功能。 也就是说,像 printfscanf 这样的函数不是语言内置语句。
  • I/O 由 C 标准库提供 标准库 <stdio.h> 中定义了常用的输入输出函数,例如:
    • printf():格式化输出到标准输出
    • scanf():从标准输入读取格式化数据
    • putchar()getchar():字符输入输出
    • fopen()fread()fwrite() 等:文件操作
  • 所以:C 语言的 I/O 是“库函数”,而不是“语言关键字或语句”。 这与一些语言(如 Python 的 print 是关键字或内建函数)不同。

四、程序阅读题(共5小题,每小题4分,共20分)

1、考察字符型变量(ASCII码 大小写转换)

非真题:(但由书上两道可能是真题的题目合成)

#include <stdio.h>

int main()
{
    char c1, c2;

    // 步骤 1:初始化
    c1 = 65;     // 考点 A:直接赋整数值
    c2 = 'b';    // 考点 A:赋字符形式

    // 步骤 2:运算(大小写转换)
    c1 = c1 + 32;  // 考点 B:大写转小写
    c2 = c2 - 32;  // 考点 B:小写转大写

    // 步骤 3:输出
    printf("%c, %d\n", c1, c1);
    printf("%c, %d\n", c2, c2);

    return 0;
}

初始化的本质(考点 A)

  • c1 = 65;
    • 内存视角: 计算机在 c1 里存入二进制的 65
    • 理解: 虽然赋值的是整数,但在 ASCII 码表中,65 对应的就是大写字母 'A'
  • c2 = 'b';
    • 内存视角: 计算机查表找到 'b' 的 ASCII 码是 98,存入二进制的 98。

运算逻辑(考点 B)

  • c1 = c1 + 32;
    • 65 + 32 = 97
    • 在 ASCII 码性质中,大写字母 + 32 = 对应的小写字母
    • 此时 c1 变成了 97(即字符 'a')。
  • c2 = c2 - 32;
    • 98 - 32 = 66
    • 在 ASCII 码性质中,小写字母 - 32 = 对应的大写字母
    • 此时 c2 变成了 66(即字符 'B')。

输出格式

  • 第一行 printf("%c, %d", c1, c1)
    • %c 输出 c1 (97) 对应的字符 \(\rightarrow\) a
    • %d 输出 c1 (97) 对应的数值 \(\rightarrow\) 97
  • 第二行 printf("%c, %d", c2, c2)
    • %c 输出 c2 (66) 对应的字符 \(\rightarrow\) B
    • %d 输出 c2 (66) 对应的数值 \(\rightarrow\) 66

答案:

a, 97
B, 66

2、考察 Sizeof 与 运算符优先级

非真题:(但由书上两道可能是真题的题目合成)

 #include <stdio.h>

int main()
{
    int a, b;

    // 考点 A:混合运算的类型提升(括号内)
    // 3(int) + 5.0(double) -> 结果类型为 double
    a = sizeof(3 + 5.0);

    // 考点 B:优先级与隐式转换(无括号)
    // sizeof 3 先算,结果再加 5.0,最后赋值给 int b
    b = sizeof 3 + 5.0;

    // 考点 C:基本数据类型与字符串(\0)
    // sizeof(short) vs sizeof("China")
    printf("%d, %d, %d, %d\n", sizeof(short), a, b, sizeof("China"));

    return 0;
}
  1. 基本类型的长度 sizeof(short)
  • 分析:这是最基础的死记硬背考点。
  • 规则short(短整型)在标准环境下通常占用 2 个字节。
  • 结果:输出 2
  1. 类型提升陷阱 a = sizeof(3 + 5.0)
  • 分析sizeof 计算的是括号内表达式运算结果的数据类型长度。
  • 过程
    • 3 是整数 (int)。
    • 5.0 默认是双精度浮点数 (double)。
    • 规则:C 语言运算时,"小类型"往"大类型"靠。int + double \(\rightarrow\) double
    • double 类型占用 8 个字节。
  • 结果:输出 8
  1. 优先级陷阱 b = sizeof 3 + 5.0
  • 分析:这里没有括号,拼的是优先级。
  • 过程
    1. 优先级sizeof 运算符的优先级 高于 + 号。
    2. 第一步:先算 sizeof 3。因为 3 是 int,所以 sizeof 3 等于 4
    3. 第二步:表达式变成了 4 + 5.0。结果是 9.0 (double)。
    4. 第三步:赋值给 int b。浮点数 9.0 被强制截断为整数 9
  • 结果:输出 9
  1. 字符串陷阱 sizeof("China")
  • 分析:肉眼看到的字符数 vs 实际内存占用。
  • 过程
    • 可见字符:C-h-i-n-a (5个)。
    • 规则:字符串常量在内存结束处必须有一个隐形的结束标记 \0
    • 计算:5 + 1 = 6。
  • 结果:输出 6

答案:

2, 8, 9, 6

3、考察嵌套循环与 Continue

可能是真题

#include<stdio.h>

int main()
{
    int i, j, n = 0;
    for(i = 0; i < 2; i++)
    {
        n++;
        for(j = 0; j <= 3; j++)
        {
            if(j % 2) continue;
            n++;
        }
        n++;
    }
    printf("n = %d\n", n);
    return 0;
}
  • 考点:逻辑流程控制,continue 跳过谁,n++ 执行了几次。

  • 解析

    • 外层 i=0: n变成1。进入内层。
    • 内层 j=0: 偶数不continue,n变成2。
    • 内层 j=1: 奇数continue (跳过n++)。
    • 内层 j=2: 偶数不continue,n变成3。
    • 内层 j=3: 奇数continue。
    • 内层结束。n变成4 (外层最后还有个n++)。
    • 外层 i=1: n变成5。重复一遍内层逻辑,n加3,变成8。
  • 答案

    n= 8
    

4、考察函数递归

#include<stdio.h>

void fun(int a,int b)
{
    if(a >= b)
        printf("%d",a);  // 【位置 A】
    else
        fun(a+1, b);     // 【位置 B】递归调用

    printf("%d",a);      // 【位置 C】这是公用的代码!无论 if 还是 else,最后都会执行这一句!
}

int main()
{
    fun(1,2);
    return 0;
}

第一层:main 调用 fun(1, 2)

  • 参数a=1, b=2

  • 判断if(1 >= 2) 不成立。

  • 执行 else:进入 【位置 B】,调用下一层递归 fun(2, 2)

    • (注意:此时第一层函数暂停在这里,等待第二层运行结束,它手里还捏着最后的 【位置 C】 没执行)

    第二层:递归调用 fun(2, 2)

    • 参数a=2, b=2
    • 判断if(2 >= 2) 成立!
    • 执行 if:进入 【位置 A】,打印 2
      • 当前屏幕:2
    • 继续执行if 语句结束,程序继续向下走。
    • 执行末尾:到达 【位置 C】,打印 2
      • 当前屏幕:22
    • 结束:第二层函数运行完毕,返回上一层。

回到第一层:fun(1, 2)

  • 继续:刚才在 【位置 B】 等待的递归调用结束了。
  • 继续向下:程序走到最后的 【位置 C】。
  • 此时的 a:在这一层,a 仍然是 1
  • 执行末尾打印 1
    • 当前屏幕:221
diagram-1767590037591-b91b5d69

答案:

221
#include<stdio.h>
void fun(int a)
{
    if(!a)
        printf("%d",a);
    else
        fun(a-1);
    printf("%d",a);
}
int main()
{
    fun(2);
    return 0;
}
0012

5、考察共用体Union

可能是真题

#include<stdio.h>

int main()
{
    union { char c; int i; } s;
    s.c = 'A'; // 内存里写入 65 (0x41)
    s.i = 2; // 内存里写入 2。因为共用地址,'A' 被覆盖成了 2。
    printf("%d%d", s.c, s.i);
    return 0;
}
  • 共用起始地址
    • char cint i 并不是分开存放的,而是从同一个内存地址开始存放
    • 可以把共用体想象成一个屋子,同一时间只能住一个人。
  • 覆盖过程(Timeline)
    • s.c = 'A':内存的第 1 个字节被写入了 65('A'的ASCII码)。
    • s.i = 2:这里是关键!int 占用 4 个字节(包含第 1 个字节)。当你写入整数 2 时,系统会将这 4 个字节全部重写(通常是 00000010 00000000... 二进制)。
    • 结果:原本那个位置的 'A' (65) 瞬间被整数 2 的低位数据覆盖掉了。
  • 输出读取
    • s.c:去读第 1 个字节 \(\rightarrow\) 发现是 2
    • s.i:去读整个 4 字节 \(\rightarrow\) 发现是 2
    • 所以输出 22,即 22

答案:

22

6、考察宏定义

可能是真题

#include<stdio.h>
#define LAB1 0
#define LAB2 2
#include<stdio.h>

void main()
{
    int temp;
    #ifdef LAB1
        temp=LAB1;
    #else
        temp=LAB2;
    #endif
    printf("%d",temp);
}
  • 区分 #ifdef #if
    • #if LAB1:这是在判断 真假。如果代码写的是这个,因为 LAB1 是 0(假),确实会跳到 else
    • #ifdef LAB1:这是在判断 存在性(Is Defined?)。它完全不关心 LAB1 的值是 0、1 还是 100,它只关心:“你在前面通过 #define 提到过 LAB1 这个名字吗?”
  • 执行逻辑
    • 第一行 #define LAB1 0 已经“注册”了 LAB1 这个名字。
    • 所以在 #ifdef LAB1 时,判定结果为 “存在”(真)。
    • 编译器会保留 temp = LAB1; 这一行代码。
    • temp = 0;
  • 总结
    • 只要 #define 出现过,#ifdef 就成立。哪怕你定义的是 #define LAB1 (后面什么都不写),它也是成立的。

答案:

0

五、算法设计题(共2小题,每小题8分,共16分)

1、考察二维数组与循环

可能是真题:

编程计算n×n的矩阵的两条对角线上所有元素(各元素数值任意)之和

#include <stdio.h>
#define N 5  // 【改这里】定义矩阵大小,如果是5就是5x5,如果是3就是3*3

int main()
{

	int a[N][N] = {
        {1, 1, 1, 1, 1},
        {1, 1, 1, 1, 1},
        {1, 1, 5, 1, 1},
        {1, 1, 1, 1, 1},
        {1, 1, 1, 1, 1}
    };

//    int a[N][N] = {
//    	{9, 4, 7},
//    	{5, 6, 1},
//    	{8, 3, 2}
//    };

    int sum = 0, i, j;

    printf("%d x %d 数组:\n", N, N);

    // 输出矩阵部分
    for(i = 0; i < N; i++)
    {
        for(j = 0; j < N; j++)
            printf("%3d", a[i][j]);
        printf("\n");
    }

    // 计算求和部分
    for(i = 0; i < N; i++)
    {
        for(j = 0; j < N; j++)
        {
            // 核心公式
            // 1. i == j 是主对角线
            // 2. i + j == N - 1 是副对角线 (3x3时是2, 5x5时是4)
            if(i == j || i + j == N - 1)
            {
                sum = sum + a[i][j];
            }
        }
    }

    printf("对角线元素之和为:%d\n", sum);
    return 0;
}

2、考察字符串与指针

可能是真题

编程使用字符指针将26个英文字母以每行10个的形式输出

#include<stdio.h>

int main()
{
    char *str1, *str2;
    str1 = "abcdefghijklmnopqrstuvwxyz";

    // 遍历字符
    for(str2 = str1; str2 < str1 + 26; str2++)
    {
        printf("%c ", *str2);

        // 判断是否换行
        // str2-str1 得到的是当前字符的下标(0-25)
        // +1 是为了变成第几个字符(1-26)
        if((str2 - str1 + 1) % 10 == 0)
            printf("\n");
    }
    return 0;
}

六、程序设计题(共2小题,每小题12分,共24分)

1、考察流程图(循环)

画出完成如下要求的程序对应的流程图:求两个自然数的最大公约数和最小公倍数

/* 【例 5.17】求两个自然数的最大公约数和最小公倍数 */
#include <stdio.h>

int main()
{
    int a, b, r, n, m;

    printf("请输入两个整数:");
    scanf("%d%d", &a, &b);

    m = a; n = b;   /* 保存原始数值,因为后面 a 和 b 会变 */

    /* 核心算法:辗转相除法 */
    do
    {
        r = a % b;  /* 求余数 */
        a = b;      /* 把除数 b 变成下一轮的被除数 a */
        b = r;      /* 把余数 r 变成下一轮的除数 b */
    } while (r != 0); /* 当余数不为0时,继续循环;余数为0,结束 */

    printf("%d和%d的最大公约数是:%d\n", m, n, a);
    printf("最小公倍数是:%d\n", m * n / a);

    return 0;
}
image-31f8f99d

2、可能还是考察画图(分支) 也可能考察程序

没有明确的暗示

自己掌握好相关知识点