【嵌入式 C 语言高频考点】周测 + 期中真题解析:从基础语法到编程实战
大家好,我是学嵌入式的小杨同学。嵌入式 C 语言的学习离不开高频刷题 ------ 周测和期中测试的真题,往往集中了最核心、最易混淆的考点,比如常量定义、指针语法、关键字用法、变量交换、字符串处理等。今天就整合两份真题卷,逐题拆解选择题、填空题、简答题的核心考点,手把手讲解编程题的多种实现思路,帮你吃透嵌入式 C 语言的 "高频考点清单",轻松应对考试和开发。
一、选择题:抓准 "易错点",避开陷阱
选择题看似基础,却容易在细节上翻车,核心考点集中在 "常量合法性""逻辑推理""运算符特性""指针步长" 等,逐题解析如下:
1. 合法常量判断(周测第 1 题)
题目 :______是 C 语言的合法常量(无正确选项,需分析错误原因)A. .45 B. 078 C. 25.6e3.4 D. 'xy'考点 :C 语言常量的语法规则解析:
- A:小数常量必须包含整数部分或小数部分,正确写法应为
0.45或.45(C 语言允许,但不规范,部分编译器视为合法,需注意); - B:以
0开头的是八进制常量,八进制仅含 0-7,078中的8非法; - C:科学计数法中,
e后面必须是整数,3.4非法; - D:字符常量用单引号包裹,仅能包含 1 个字符,
'xy'是 2 个字符,非法。结论:题目可能存在疏漏,严格来说无完全合法选项,核心是掌握不同常量的语法规范。
2. 逻辑推理题(周测第 2 题)
题目 :甲、乙、丙、丁四人供词仅 1 个假,破案结果是(B)甲:我不是作案的 乙:丁是罪犯 丙:乙是罪犯 丁:作案的不是我A. 甲作案 B. 乙作案 C. 丙作案 D. 丁作案考点 :逻辑矛盾分析(嵌入式开发中 "条件判断" 的思维基础)解析:
- 乙和丁的供词矛盾(乙说丁是罪犯,丁说自己不是),因此必有 1 个假、1 个真;
- 已知仅 1 个假供词,因此甲和丙的供词为真;
- 丙说 "乙是罪犯" 为真,因此答案是 B。
3. 运算符适用类型(期中第 1 题)
题目 :运算对象必须是整型的运算符是(A)A. % B. / C. == D. <=考点 :取模运算符%的特性解析:
%(取模)仅支持整型,用于计算余数,浮点型会编译报错;/(除法)支持整型和浮点型(整型除法舍弃小数);==(等于)、<=(小于等于)是关系运算符,支持任意算术类型。
4. 指针步长计算(期中第 3 题)
题目 :64 位 CPU 中,long *p=(long *)0x1000; p++; 输出p的结果是(D)A. 0x1000 B. 0x1001 C. 0x1004 D. 0x1008考点 :指针自增的步长规则解析:
- 指针步长 = 指向数据类型的大小,64 位系统中
long占 8 字节; p++会让指针地址增加 8,因此0x1000 + 8 = 0x1008。
5. 有符号与无符号比较(期中第 4 题)
题目 :int a=-1; unsigned int b=-1; int c=a==b?1:0; 则 c 的值是(C)A. -1 B. 0 C. 1 D. 表达式不合法考点 :混合类型比较的隐式转换解析:
- 有符号与无符号比较时,有符号数隐式转为无符号数;
a=-1(int)转无符号后是最大值(如 32 位为0xFFFFFFFF),与b=-1(unsigned int)的存储值相同,因此a==b为真,c=1。
二、填空题:吃透 "语法细节",精准计算
填空题考察 "自增运算符""宏定义替换" 等细节,易错点在于 "运算符优先级""宏替换的纯粹性",逐题解析:
1. 自增运算符计算(周测第 1 题)
题目:以下代码的输出结果是______
c
运行
#include <stdio.h>
int main(void){
int a,b,c,d;
a=10;
b=a++; // 后置自增:先赋值,再自增
c=++a; // 前置自增:先自增,再赋值
d=10*a++; // 后置自增:先计算10*a,再自增
printf("b,c,d:%d,%d,%d",b,c,d);
return 0;
}
考点 :前置 / 后置自增的执行顺序解析:
b=a++:a 先赋值给 b(b=10),a 自增为 11;c=++a:a 先自增为 12,再赋值给 c(c=12);d=10*a++:先计算 10*12=120(d=120),a 自增为 13;输出结果 :b,c,d:10,12,120
2. 宏定义替换计算(周测第 2 题)
题目 :#define MUL(x,y) x*y; int a=3,b=5; printf("%d\n",MUL(b,a+4)); 输出结果是______考点 :宏定义的 "纯粹文本替换" 特性(无优先级处理)解析:
- 宏替换仅替换文本,不添加括号,
MUL(b,a+4)替换为5*3+4; - 按运算符优先级,先算乘法再算加法:
5*3=15+4=19;输出结果 :19避坑技巧 :宏定义中参数需加括号,避免优先级问题,正确写法:#define MUL(x,y) (x)*(y),替换后为(5)*(3+4)=35。
三、简答题:理清 "核心概念",精准作答
简答题考察对 "指针定义""关键字作用""常量区别" 的理解,答案需简洁准确,直击要点:
1. 复杂指针 / 数组定义的含义(周测第 1 题)
题目 :解释以下a的含义
int *a2)int **a3)int *a[10]4)int (*a)[10]5)int (*a)(int)6)int (*a[10])(int)考点 :指针、数组、函数指针的定义语法(嵌入式开发高频考点)标准答案:int *a:指向整型数的指针;int **a:指向 "整型指针" 的指针(二级指针);int *a[10]:有 10 个元素的数组,每个元素是指向整型数的指针(数组优先级高于*);int (*a)[10]:指向 "10 个整型数数组" 的指针(括号提升*优先级);int (*a)(int):指向函数的指针,函数有 1 个整型参数,返回整型;int (*a[10])(int):有 10 个元素的数组,每个元素是指向 "有 1 个整型参数、返回整型的函数" 的指针。
2. '10'、'0'、0、NULL的作用(周测第 2 题)
考点 :不同常量的本质区别(嵌入式开发中 "判空""赋值" 的基础)标准答案:
'10':非法字符常量(单引号内 2 个字符),无合法作用;'0':字符常量,ASCII 码值为 48,用于表示字符'0'(如字符串中的数字字符);0:整型常量,值为 0,可用于变量初始化、条件判断(如if(a==0));NULL:宏定义常量,本质是(void *)0,用于指针初始化(表示指针指向空地址),避免野指针(如int *p=NULL)。
3. static、extern、const 关键字的作用(期中第 8 题)
考点 :关键字对作用域、生命周期、可修改性的影响标准答案:
static:- 修饰局部变量:延长生命周期(从栈区移到静态存储区),不改变作用域;
- 修饰全局变量 / 函数:限制作用域为当前文件,禁止外部文件通过
extern调用;
extern:声明外部全局变量 / 函数(仅声明不定义),支持跨文件调用;const:修饰变量为只读(值不可修改),修饰指针时可限制 "指向的值" 或 "指针本身" 不可改,提升代码安全性。
4. 形参和实参的区别,是否可以重名?(期中第 9 题)
考点 :参数传递的本质(嵌入式函数调用的基础)标准答案:
- 区别:
- 定义位置:形参在函数定义时声明(如
void func(int x)),实参在函数调用时传入(如func(5)); - 内存分配:形参在函数调用时分配内存,函数结束后释放;实参内存由定义位置决定(全局变量在静态区,局部变量在栈区);
- 传递方式:实参通过 "值传递" 或 "地址传递" 给形参(形参是实参的副本);
- 定义位置:形参在函数定义时声明(如
- 能否重名:可以,形参作用域是函数内部,与外部实参互不影响。
四、编程题:多种思路实现,应对不同场景
编程题考察 "逻辑设计" 和 "语法灵活运用",真题中 "变量交换""字符串处理" 是高频题型,以下提供多种实现思路:
1. 整型变量 a、b 的三种以上交换方法(周测上机题)
核心要求:交换两个变量的值,不依赖第三方库,适配嵌入式场景。
方法 1:临时变量法(最常用,稳定可靠)
c
运行
#include <stdio.h>
int main() {
int a=3, b=5;
int temp = a; // 临时变量存储a的值
a = b;
b = temp;
printf("a=%d, b=%d\n", a, b); // 输出a=5, b=3
return 0;
}
特点:逻辑简单,无数据溢出风险,嵌入式开发首选。
方法 2:算术运算法(无临时变量)
c
运行
#include <stdio.h>
int main() {
int a=3, b=5;
a = a + b; // a=8
b = a - b; // b=8-5=3
a = a - b; // a=8-3=5
printf("a=%d, b=%d\n", a, b);
return 0;
}
特点 :无临时变量,但a+b可能溢出(如 a、b 为大整数),嵌入式中慎用。
方法 3:异或运算法(无临时变量,无溢出)
c
运行
#include <stdio.h>
int main() {
int a=3, b=5;
a = a ^ b; // 异或:相同为0,不同为1
b = a ^ b; // 恢复a的原始值(b=3)
a = a ^ b; // 恢复b的原始值(a=5)
printf("a=%d, b=%d\n", a, b);
return 0;
}
特点:仅适用于整型变量,无数据溢出,嵌入式高频使用(如寄存器操作)。
方法 4:指针法(嵌入式函数传参场景)
c
运行
#include <stdio.h>
void swap(int *p, int *q) {
int temp = *p;
*p = *q;
*q = temp;
}
int main() {
int a=3, b=5;
swap(&a, &b); // 传递地址
printf("a=%d, b=%d\n", a, b);
return 0;
}
特点:适用于函数间变量交换,是嵌入式开发的常用场景。
2. 手动实现字符串四大核心函数(指针形式)(期中编程题 1)
题目 :不使用<string.h>,用指针实现strcpy(复制)、strcat(拼接)、strcmp(比较)、strlen(长度)。
完整实现代码
c
运行
#include<stdio.h>
// 1. 字符串复制:d = s(d需足够大)
char* Strcpy(char *d, const char *s) {
if (d == NULL || s == NULL) return NULL;
char *p = d; // 保存d的原始地址
while (*s != '\0') {
*d = *s;
d++;
s++;
}
*d = '\0'; // 手动添加结束符
return p;
}
// 2. 字符串拼接:d += s
char* Strcat(char *d, const char *s) {
if (d == NULL || s == NULL) return NULL;
char *p = d;
while (*d != '\0') d++; // 遍历到d末尾
while (*s != '\0') {
*d = *s;
d++;
s++;
}
*d = '\0';
return p;
}
// 3. 字符串长度:返回有效字符个数(不含'\0')
int Strlen(char *d) {
if (d == NULL) return 0;
int len = 0;
while (*d != '\0') {
len++;
d++;
}
return len;
}
// 4. 字符串比较:返回*d - *s(相等返回0)
int Strcmp(char *d, char *s) {
if (d == NULL || s == NULL) return -1;
while (*d != '\0' && *s != '\0') {
if (*d != *s) return *d - *s;
d++;
s++;
}
return *d - *s; // 处理长度不同的情况
}
// 测试
int main() {
char a[1024] = {0};
const char *s1 = "helloworld";
const char *s2 = "12345";
char *s3 = "helloworld12345";
char *s4 = "helloworld67890";
Strcpy(a, s1);
printf("1.Strcpy: %s\n", a); // helloworld
printf("2.Strlen: %d\n", Strlen(a)); // 10
Strcat(a, s2);
printf("3.Strcat: %s\n", a); // helloworld12345
printf("4.Strcmp(a,s3): %d\n", Strcmp(a, s3)); // 0(相等)
printf(" Strcmp(a,s4): %d\n", Strcmp(a, s4)); // -5('1' < '6')
return 0;
}
3. 统计字符出现次数(不区分大小写)(期中编程题 2)
题目:输入字母数字字符串和目标字符,输出出现次数(不区分大小写)。
c
运行
#include<stdio.h>
#include<string.h>
int count_char(const char *str, char c) {
int count = 0;
if (str == NULL) return 0;
while (*str != '\0') {
char current = *str;
char target = c;
// 统一转为小写
if (current >= 'A' && current <= 'Z') current += 32;
if (target >= 'A' && target <= 'Z') target += 32;
if (current == target) count++;
str++;
}
return count;
}
int main() {
char a[1024];
char target;
printf("请输入字符串:");
fgets(a, sizeof(a), stdin);
a[strcspn(a, "\n")] = '\0'; // 截断换行符
printf("请输入目标字符:");
scanf("%c", &target);
printf("出现次数:%d\n", count_char(a, target));
return 0;
}
4. 统计单词个数(空格分隔)(期中编程题 3)
题目:输入字符串,统计单词个数(单词间用空格分隔)。
c
运行
#include<stdio.h>
#include<string.h>
int count_words(const char *str) {
if (str == NULL) return 0;
int count = 0;
int in_word = 0; // 0:单词外,1:单词内
while (*str != '\0') {
if (*str == ' ') {
in_word = 0;
} else if (in_word == 0) {
count++;
in_word = 1;
}
str++;
}
return count;
}
int main() {
char a[1024];
printf("请输入字符串:");
fgets(a, sizeof(a), stdin);
a[strcspn(a, "\n")] = '\0';
printf("单词个数:%d\n", count_words(a));
return 0;
}
五、总结:嵌入式 C 语言高频考点清单
整合两份真题,核心考点可归纳为以下 4 类,建议重点突破:
- 基础语法:常量合法性、自增运算符、宏定义替换、关键字作用;
- 指针与数组:复杂指针 / 数组定义、指针步长、二级指针、函数指针;
- 逻辑与运算:逻辑推理、运算符特性(%、异或)、混合类型比较;
- 编程实战:变量交换(多种方法)、字符串处理(指针实现)、统计类问题。
学习建议:
- 选择题 / 填空题:重点关注 "易错点"(如宏替换无优先级、指针步长与类型相关);
- 简答题:熟记指针 / 数组 / 关键字的核心定义,避免表述模糊;
- 编程题:多练习 "无库函数实现",掌握指针遍历、状态标记法等核心技巧。
掌握这些考点,不仅能应对考试,更能为嵌入式开发中的驱动编写、数据处理打下基础。我是学嵌入式的小杨同学,关注我,后续会分享更多嵌入式实战技巧!