Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

C语言错题封面

记录学习过程中错误、混淆的 C 语言知识点,持续更新……


第 1 题:^ 和 << 的优先级

设有以下语句:

1
2
char a = 3, b = 6, c;
c = a ^ b << 2;

则 c 的二进制值是 ______。

❌ 我的错误答案:0100(即十进制 4)
错误原因:混淆了 ^ 和 << 的优先级,误以为按位异或先于左移,于是先计算 a ^ b,再左移 2 位。

✅ 正确解析:在 C 语言中,左移运算符 << 的优先级高于按位异或 ^,所以原式等价于 a ^ (b << 2)。
计算过程:6 << 2 = 24(二进制 11000),3 ^ 24 = 27(二进制 11011)。

正确答案:11011(十进制 27)


第 2 题:结构体指针与成员访问

根据以下定义,错误的表达式是:

1
2
struct { int a; char b; } Q, *p = &Q;
A. Q.a B. (*p).b C. p->a D. *p.b

❌ 我的错误倾向:容易混淆 *p.b 与 (*p).b,忽略了成员运算符 . 的优先级高于解引用 *。

✅ 正确解析:成员访问运算符 . 的优先级高于解引用运算符 *,因此 *p.b 会被解析为 *(p.b)。但 p 是指针,不能直接用 . 访问成员,必须写作 (*p).b 或 p->b。

正确答案:D. *p.b


第 3 题:结构体首地址与强制类型转换

分析以下代码的运算结果:

1
2
3
4
5
6
struct node {
int a; int b; int c;
};
struct node s = {3, 5, 6};
struct node *pt = &s;
printf("%d\n", *(int *)pt);

❌ 我的错误答案:6
错误原因:误以为指针 pt 指向结构体的末尾(成员 c),实际上指针存储的是结构体的首地址。

✅ 正确解析:结构体在内存中连续分布,其首地址即第一个成员 a 的地址。(int *)pt 将结构体指针强转为整型指针,解引用后读取从首地址开始的 int 大小数据,正好是成员 a 的值。

正确答案:3


第 4 题:冒泡排序实现

用 C 语言对数组 a[10] = {6, 2, 8, 11, 0, 7, 3, -3, 9, 12} 进行升序排列。

❌ 我的错误状态:对排序算法的双重循环逻辑不熟练,不知道如何通过嵌套循环实现元素比较与交换。

✅ 正确解析(冒泡排序):核心思想是两两比较相邻元素,如果反序则交换,每轮将当前最大值“冒泡”到数组末端。

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>

int main() {
int a[10] = {6, 2, 8, 11, 0, 7, 3, -3, 9, 12};
int i, j, temp;

// 外层循环:控制轮数(10 个数需 9 轮)
for (i = 0; i < 9; i++) {
// 内层循环:每轮两两比较,最大值沉底
for (j = 0; j < 9 - i; j++) {
if (a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}

// 打印排序结果
for (i = 0; i < 10; i++) {
printf("%d ", a[i]);
}
return 0;
}

运行结果:-3 0 2 3 6 7 8 9 11 12


第 5 题:转义字符 '\101'

若有定义:char c = '\101'; 则变量 c 中包含的字符个数为多少,是哪些字符?

❌ 我的错误答案:1,5。错误认为是二进制转十进制。

✅ 正确答案:1,A。
遇到 \数字,就是八进制;\x 才是十六进制。
'\101' 表示八进制数 101,转换为十进制是 65,对应 ASCII 字符 'A'。


第 6 题:输入年份,判断是否闰年

输入一个年份,判断该年份是否为闰年。

✅ 核心知识点:闰年判断条件

满足以下任意一个条件,就是闰年:

  1. 能被 4 整除,但不能被 100 整除;
  2. 能被 400 整除。

对应的 C 语言逻辑表达式为:

1
(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main() {
int year;

printf("请输入年份:");
scanf("%d", &year);

if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
printf("%d 是闰年\n", year);
} else {
printf("%d 不是闰年\n", year);
}

return 0;
}

第 7 题:&&中若左假的重点(同理||也是)

a=5,b=6,c=7,d=8,m=2,n=2,求 (m=a>b)&&(n=c>d) 后 n 的值。
答案:C) 2
重点:a>b 为假,m=0,&& 短路,右边不执行,所以 n 仍为 2。

第 8 题:运算符了解一下该点即可

a=12,求 a += a -= a *= a 后 a 的值。
答案:a=0
重点:从右向左且 a 同时改变:a*=a 后 a=144;a-=144 后 a=0;>a+=0 后 a=0。

第 9 题:指针下标越界

若有以下定义,则对 a 数组元素的正确引用是( D )。
int a[5], *p = a;
A) *&a[5](下标越界)
B) a + 2(不是元素,是地址 &a[2])
C) *(p + 5)(下标越界)
D) *(a + 2)(正确,等价于 a[2])
答案:D
注意:没注意下标越界

第 10 题:二维数组a中的*(a + j)

若有定义:int a[2][3];,则对 a 数组的第 i 行 j 列元素地址的正确引用为( D )。
A) *(a[i]+j)
B) (a+i)
C) *(a+j)(得到的是 a[j][0] 的地址)
D) a[i]+j
答案:D
注意:*(a+j) 等价于 a[j](这里的j相当于行下标了)。

第 11 题:printf("%ld")输出地址(能打印,但不规范)

下面程序段的运行结果是( C )。

1
2
3
>char *s = "abcde";
>s += 2;
>printf("%ld", s);

A) cde
B) 字符 'c'
C) 字符 'c' 的地址
D) 无确定的输出结果
答案:C
注意:printf("%ld", s) 试图以十进制长整型不规范来输出 s 的值,也就是字符 'c' 的地址。

第 12 题:16进制地址的加法

以下程序段的执行结果是:2016 2041

1
2
3
4
5
>unsigned char *p1;
>unsigned long *p2;
>p1 = (unsigned char *)0x10002011;
>p2 = (unsigned long *)0x10002021;
>printf("p1=%p,p2=%p", p1 + 5, p2 + 4);

答案:p1=0x10002016,p2=0x10002041,低四位为 2016 2041
注意:0x表示16位,0x中一个数是由4位组成,p1 是 unsigned char *,加 5 移动 5 字节,得到 0x10002016;p2 是 unsigned long *,加 4 移动 4 * sizeof(unsigned long) 字节。若 unsigned long 占 8 字节,则移动 32 字节,即 0x20,得到 0x10002041。

第 13 题:++与(…++)

以下程序段的执行结果为 7 8。

1
2
3
4
5
>int arr[] = {6, 7, 8, 9, 10};
>int *ptr = arr;
>*(ptr++) += 123;
>printf(" %d", *ptr);
>printf(" %d", *(++ptr));

答案:7 8
注意:++与括号无关,就算有括号,也是先用它的值。*(ptr++) += 123 先取 ptr 当前指向的 arr[0],将其值加 123,然后 ptr 自增指向 arr[1]。所以 arr[0] 变为 129,*ptr 输出 arr[1] 的值 7;*(++ptr) 先让 ptr 自增到 arr[2],再解引用,输出 8。

第 14 题:C 语言程序的组成

一个 C 语言程序是由 ______。

A. 一个主程序和若干个子程序组成
B. 函数组成
C. 若干过程组成
D. 若干子程序组成

❌ 我的错误答案:A
错误原因:把其他语言里“主程序 + 子程序”的说法套到了 C 语言上,也忽略了 C 程序可以只有一个 main 函数。

✅ 正确解析:C 语言程序的基本组成单位是函数。一个 C 程序由一个或多个函数组成,其中必须有且仅有一个 main 函数(主函数),程序从 main 函数开始执行。其他函数可以被调用,也可以没有。

注意:C 语言中没有“过程”这种标准说法;选项 A、D 的“主程序 / 子程序”也不是 C 语言的规范表述。

正确答案:B. 函数组成


.char str[] = “Hello”; sizeof ( str )= 6
char *p = str ; sizeof ( p ) = 8
int n = 10; sizeof ( n ) = 4
void Fun(int a[5])
{ sizeof(a)=8 //填成20了
}

第 15 题:sizeof 计算数组与指针

1
2
3
4
5
6
7
8
9
10
11
12
13
char str[] = "Hello";
sizeof(str); // 6

char *p = str;
sizeof(p); // 8(64 位系统)

int n = 10;
sizeof(n); // 4

void Fun(int a[5])
{
sizeof(a); // 8(64 位系统),不是 20
}

❌ 易错点:把 Fun 中的 sizeof(a) 填成 20。
✅ 正确解析:函数参数中的 int a[5] 会退化为 int *a,sizeof(a) 计算的是指针大小。
64 位系统为 8,32 位系统为 4,不是数组总大小 20。


第 16 题:统计字符出现次数(不区分大小写)

题目:输入一个由字母和数字组成的字符串,接着输入一个字符。输出该字符在给定字符串中的出现次数,不区分大小写(借助函数实现)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>

char To_Small(char ch);

int main()
{
char buf[32] = {0};
char ch = 0;
int count = 0;

gets(buf);
scanf("%c", &ch);

ch = To_Small(ch);

for (int i = 0; buf[i] != '\0'; i++)
{
if (To_Small(buf[i]) == ch)
count++;
}

printf("count = %d\n", count);
return 0;
}

char To_Small(char ch)
{
if (ch >= 'A' && ch <= 'Z')
return ch + 32;
else
return ch;
}

第 17 题:统计单词个数

题目:用户输入一段字符串,并统计其中的单词个数,假设单词之间用空格隔开,不考虑其他特殊字符。字符串最大长度不超过 1024。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <string.h>

int main()
{
char buf[1024] = {0};
int count = 0, flag = 0;

gets(buf);
long length = strlen(buf);

for (int i = 0; i < length; i++)
{
if (buf[i] == ' ')
flag = 0;

if (flag == 0 && buf[i] != ' ')
{
count++;
flag = 1;
}
}

printf("count = %d", count);
return 0;
}

第 18 题:寻找数组中的“幸运数”

题目描述:在一个整数数组中,如果一个数字的出现次数恰好等于它本身的值,我们就称这个数字为“幸运数”。例如,在数组 {1, 2, 2, 1, 3, 3} 中,数字 2 出现了 2 次,所以 2 是幸运数。请编写一个 C 语言程序,实现找出幸运数字中最大的那个,没有就显示“没有幸运数字”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>

int Fun(int *p, int n);

int main()
{
int num[5] = {0};
int i = 0;

for (i = 0; i < 5; i++)
scanf("%d", &num[i]);

int res = Fun(num, 5);

if (res == -1)
printf("没有幸运数字\n");
else
printf("幸运数字 = %d\n", res);

return 0;
}

int Fun(int *p, int n)
{
int max = -1, count = 0;
int i = 0, j = 0;

for (i = 0; i < n; i++)
{
count = 0;

for (j = 0; j < n; j++)
{
if (p[i] == p[j])
count++;
}

if (p[i] == count && p[i] > max)
max = p[i];
}

return max;
}

说明:使用两个 for 循环统计每个数字的出现次数,时间复杂度为 O(n²)。
如果数据量较大,可以用哈希表或数组下标计数优化到平均 O(n)。


持续更新中……

评论