C语言易错题集 第三部
C语言 错题
2023-09-11 14:15:52 时间
目录
一、C语言程序exe相关
用 C 语言编写的源程序须经过编译连接后,生成扩展名为 .exe 的可执行文件,才能运行。()
A 正确
B 错误
答案: B
C语言编写的程序,肯定是要经过一系列的编译,链接,生成可执行的文件。
在windows系统中,执行文件都是.exe为扩展名的。
不过在linux系统中就不一样了,linux系统并不区分扩展名,所以也就无所谓什么.exe之类的文件,
只要知道最终生成可执行的二进制文件就可以了。
二、sizeof和strlen相关
下面程序的输出结果为多少(32位机器上)?
#include<stdio.h>
#include<string.h>
void Func(char str_arg[2])
{
int m = sizeof(str_arg);
int n = strlen(str_arg);
printf("%d\n", m);
printf("%d\n", n);
}
int main(void)
{
char str[] = "Hello";
Func(str);
}
A 5 5
B 5 4
C 4 5
D 4 4
答案: C
1,对于void Func(charstr_arg[2]) 这一句不要被那个2误导了
下面这些写法都可以的。
voidFunc(charstr_arg[])
voidFunc(charstr_arg[1])
voidFunc(charstr_arg[2])
voidFunc(charstr_arg[3])
voidFunc(charstr_arg[4])
...
voidFunc(charstr_arg[200])
...
也可以写成
voidFunc(char *str_arg)
之所以能这样写,是因为Func的参数是一个地址
2,对于sizeof的参数,是一个指针,因为这是32位系统, 32 = 8*4,需要4字节存储指针。
如果是64位系统 64 = 8*8,需要8字节
3,对于strlen,就是字符串的长度,"Hello"长度是5
三、小端存储相关
在x86的机器上,int a=0xabcd1234 char b=((char*)&a)[0]请问b是多少
A 0xa
B 0x4
C 0xab
D 0x34
答案: D
x86是小端存储,即高位存储在高地址,低位存储在低地址。
int a = 0xabcd1234;
内存中 ab cd 12 34,b作为一个char,右边表达式指针指向为' 4 '转化为16进制为 0x34.
高 --> 低
四、break和continue相关
C语言中break和continue语句说法正确的是()
A break语句只应用于循环体中
B continue语句只应用于循环体中
C break是无条件跳转语句,continue不是
D break和continue的跳转范围不够明确,容易产生问题
答案: B
A:break语句可以用于循环语句中,终止当前循环;也用于在switch语句中结束一个case 。A项错误。
B:continue语句只能用于循环语句,正确。
C:无条件跳转语句有return , break , continue , goto 。C项错误。
D:在switch语句中,break用来使执行流程跳出switch语句。
在循环语句中,break语句用来使执行流无条件跳出本层循环体。
continue的功能是:结束本次循环,接着进行下一次是否执行循环的条件判定。break和continue语句跳转范围明确。D选项错误。
综上本题选B。
五、函数声明相关
若有以下程序
#include<stdio.h>
void f(int n);
int main() {
void f(int n);
f(5);
}
void f(int n)
{
printf("%d\n",n);
}
则以下叙述中不正确的是()。
A 若只在主函数中对函数f进行说明,则只能在主函数中正确调用函数f
B 若在主函数前对函数f进行说明,则在主函数和其后的其它函数中都可以正确调用函数f
C 对于以上程序,编译时系统会提示出错信息:提示对对f函数重复说明
D 函数f无返回值,所以可用void将其类型定义为无值型
答案: A C
A 若只在主函数中对函数f进行说明,则只能在主函数中正确调用函数f
//解释: 在f函数定义的后面,其它的函数也是可以调用f函数的
B 若在主函数前对函数f进行说明,则在主函数和其后的其它函数中都可以正确调用函数f
//正确
C 对于以上程序,编译时系统会提示出错信息:提示对f函数重复说明
//解释: 在C语言中变量或函数可以重复声明,但是不能重复定义
D 函数f无返回值,所以可用void将其类型定义为无值型
//正确
六、递归相关
下列代码的输出是?(注:print已经声明过)
main()
{
char str[]="Geneius";
print (str);
}
print(char *s)
{
if(*s){
print(++s);
printf("%c",*s);
}
}
A suiene
B neius
C run-time error
D suieneG
答案: A
1、*s为G,执行print(e),printf(e)被压入倒数第1层,应该输出e;
2、*s为e,执行print(n),printf(n)被压入倒数第2层,应该输出n;
3、*s为n,执行print(e),printf (e) 被压入倒数第3层,应该输出e;
4、*s为e,执行print(i),printf (i) 被压入倒数第4层,应该输出i;
5、*s为i,执行print(u),printf (u) 被压入倒数第5层,应该输出u;
6、*s为u,执行print(s),printf (s) 被压入倒数第6层,应该输出s;
7、*s为s,执行print(\0),printf (\0) 被压入倒数第7层,应该输出空格;
8、开始跳出print,从上向下得到压入栈中的printf,得到最后结果“ suiene”
七、预处理相关
源程序中凡是行首以#标识的控制行都是预处理指令。以上描述是否正确?
A 正确
B 错误
答案: A
C语言有效的预处理命令总是以“#”开头
(1)头文件包含#include
(2)宏定义 #define
(3)条件编译 #ifdef #endif
八、C语言程序的最小单元相关
C语言源程序的最小单位是()。
A 程序行
B 语句
C 函数
D 字符
答案: D
C语言源程序的最小单位是字符,最小执行单元是函数。
九、指针相关
要使指针变量p指向2维数组A的第1个元素,正确的赋值表达式是()。
A p=A或p=A[0]
B p=A[0]或p=A[0][0]
C p=A[0]或p=&A[0][0]
D p=A或p=&A[0][0]
答案: C
bingle头像bingle
P=A, 是错误的,A代表的是二维数组中,数组A[0]的地址,和元素A[0][0]的地址在 数值上是一样的,
但是不能直接把A赋给P,原因是它们的类型不同。
A[0][0]是二维数组,*p相当于一维数组,类型不同
十、数组初始化相关
下面对一维数组 a 进行正确的初始化的语句是()
int a[10] = (0, 0, 0, 0, 0);
int a[10] = {};
int a[10] = {10};
int a[10] = {10, 0, -1.23};
答案: B C D
A: 是小括号,错误,应为大括号。
D: 浮点数会被强制的转换为整数,所以正确
十一、链接相关
由多个源文件组成的C程序,经过编辑、预处理、编译、链接等阶段会生成最终的可执行程序。下面哪个阶段可以发现被调用的函数未定义?
A 预处理
B 编译
C 链接
D 执行
答案: C
链接是将各个编译单元中的变量和函数引用与定义进行绑定,保证程序中的变量和函数都有对应的实体,
若被调用函数未定义,就在此过程中会发现。编辑阶段创建和修改源程序;预处理阶段分析宏定义以及替换宏引用;
编译过程是把源程序翻译为与之等价的目标程序。
十二、负数变无符号数相关
有如下C语言程序段
short si = -32767;
unsigned short usi = si;
执行上述两条语句后,usi的值为 ( )
A -32767
B 32767
C 32768
D 32769
答案: D
因C语言中的数据在内存中为补码表示形式
先把-32767表示成原码形式是(因为补码不是一步可以得到的,先原码再补码)
(-32767)原码=1111 1111 1111 1111
(-32767)补码 =1000 0000 0000 0001
再把这个补码赋给usi,usi会把最高位符号位1也当做数值位
usi=1000 0000 0000 0001=32769
十三、负数变无符号数相关
#include<stdio.h>
int main()
{
unsigned char i=7;
int j=0;
for(;i>0;i-=3)
{
++j;
}
printf("%d\n",j);
return 0;
}
请问该程序的输出是多少?
A 2
B 死循环
C 173
D 172
答案: C
这题正着推不容易,可以考虑反着推
要想退出循环 最后必定是 i=0
0~255 是256个数
根据选项
A: (0 + 2*3) % 256 = 6 不是7 , 所以A错误
C: (0 + 173*3) % 256 = 7 , 所以C可以
D: (0 + 172*3) % 256 = 4 不是7,所以D错误
B: 既然C可以,当然B就错误
第二种思路:
-2的原码是1000 0010,反码是1111 1101,补码是1111 1110,计算机中存储的是补码,
即存的是1111 1110,又因为这里是无符号的,所以最高位的1不代表符号,
所以1111 1110为254,同理,依次推,直到i为0,可得一共173次
7 4 1——3次
254 251....2——85次
255 252....3——85次
3-3为0,就不会进入循环了,一共173次
十四、union相关
A 1 4
B 4 4
C 1 2
D 4 8
答案: D
十五、switch()相关
若有以下程序
#include<stdio.h>
main()
{
int s=0,n;
for(n=0; n<4; n++)
{
switch(n)
{
default:s+=4;
case 1:s+=1;
case 2:s+=2;
case 3:s+=3;
}
}
printf ("%d\n",s);
}
则程序的输出结果是?
A 6
B 18
C 10
D 24
答案: D
第1次:s=0+4+1+2+3=10;
和case 1,2 3,依次比对,最后没有匹配的执行default 这时候开关相当于打开了,执行后面全部的。
第2次:s=10+1+2+3=16;
第3次:s=16+2+3=21;
第4次:s=21+3=24.
在switch-case语句中,多个case可以共用一条执行语句,如:
case 常量表达式1:
case 常量表达式2:
case 常量表达式3:
语句;
break;
由此可以看出case语句的作用:
case后面的常量表达式实际上只起语句标号作用,而不起条件判断作用,即“只是开始执行处的入口标号”。
因此,一旦与switch后面圆括号中表达式的值匹配,就从此标号处开始执行;
而且执行完一个case后面的语句后,若没遇到break语句,就自动进入下一个case继续执行,
而不再判断是否与之匹配,直到遇到break语句才停止执行,退出switch语句。
因此,若想执行一个case分之后立即跳出switch语句,就必须在此分支的最后添加一个break语句。