C++期末、笔试易错题整理含答案,解析(三)

文章列举并解析了一系列C++编程中的错题,涉及循环控制表达式、指针运算、宏定义、数组边界、函数参数传递、内存区域、链表操作、动态内存和虚函数等方面,旨在帮助读者理解并避免这些常见错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

错题1

C/C++中,t为int类型,进入下面的循环之前,t的值为0

while(t=1)
{
    -------
}

则以下叙述中正确的是

A.循环控制表达式的值为0
B.循环控制表达式的值为1
C.循环控制表达式不合法
D.以上说法都不对

答案 C

解析

这个表达式是赋值表达式,将1赋给t,t一直为1(真),对java语言,本题选C,java中判断条件赋值只接受boolean类型。

错题2

在 gcc 环境下,已知数组 int arr[5]={1,2,3,4,5}; 则 ((&arr+1)-1) 的结果为

答案 5

解析

&arr + 1 是 &arr 向后移动整个数组所占字节数(5 x 4 = 20)得到的地址,&arr + 1 的值和 *(&arr + 1)的值相等,*(&arr + 1) - 1 是 *(&arr + 1)向前移动4个字节得到的,因此*(*(&arr + 1) - 1)的值为数组中最后一个元素的值,代码中给出了两个整型数组,运行后得到的结果都是数组中最后一个元素的值。

错题3

以下代码的输出结果是?

#include <stdio.h>
#define a 10 

void foo();  
int main(){ 
   printf("%d..", a); 
   foo(); 
   printf("%d", a); 
} 
void foo(){ 
   #undef a 
   #define a 50 
}

答案 10…10

解析

宏定义是在编译器预处理阶段中就进行替换了,替换成什么只与define和undefine的位置有关系,与它们在哪个函数中无关

image-20230102101556615 image-20230102101610377

错题4

下面这个程序执行后会有什么错误或者效果:

#define MAX 255
int main(){
     unsigned char A[MAX], i;
     for (i = 0; i <= MAX; i++)
         A[i] = i;
}

答案 数组越界和死循环

死循环加数组越界访问(C/C++不进行数组越界检查)
MAX=255
数组A的下标范围为:0…MAX-1,这是其一…
其二.当i循环到255时,循环内执行:
A[255]=255;
这句本身没有问题…但是返回for (i=0;i<=MAX;i++)语句时,
由于unsigned char的取值范围在(0…255),i++以后i又为0了…无限循环下去.

错题5

对于以下变量定义,正确的赋值是()

int *p[3], a[3];

A.p=a
B.*p=a [0]
C.p=&a [0]
D.p[0]=&a[0]

答案 D

解析:

p[3]为存放三个指针的指针数组,题目的意思是将三个指针分别指向a数组中的三个值需要进行的完整或者其中一个步骤,对于A,p为指针数组地址,关于p的操作都是错误的,ac排除,关于B,a[0]为第一个元素的值,明显不对,故D正确。

2023.1.4

错题6

以下函数调用语句中实参的个数是( )

exce((v1, v2), (v3, v4, v5), v6);

答案 3

解析

这是运用了逗号表达式。逗号表达式的一般形式为:表达式1,表达式2,逗号表达式的求解过程是:先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值。

2023.1.5

错题7

执行下面的程序段,语句3的执行次数为(其中n>1)()

for (i = 0; i <= n-1; i++)   // (1)
    for (j = n; j > i; j--) // (2)
        state;               // (3)

答案 n(n+1)/2

解析

假设代入法:

  • ​ 设n=3,外层循环i的取值为0,1,2

  • ​ 当i=0时,内部循环j的取值为3,2,1,所以state执行3次;当i=1时,内部循环j的取值3,2,所以state执行2次;当i=2时,内部循环j的取值为3,所以state执行1次。

  • ​ 综上所述:3+2+1=6次。将n=3带入选项中的出C符合结果。

    错题8

    给定下面函数:整数单链表作为参数,函数重新排列列表的元素。

    现以顺序为 1, 2, 3, 4, 5, 6, 7 的整数列表调用该函数 ,函数执行后列表的内容是()

struct node
{
    int value;
    struct node *next;
};
 
void rearrange(struct node *list)
{
   struct node *p, * q;
   int temp;
   if ((!list) || !list -> next)
      return;
   p = list;
   q = list -> next;
   while(q)
   {
       temp = p -> value;
       p -> value = q -> value;
       q -> value = temp;
       p = q -> next;
       q = p ? p -> next:0;
   }
} 
A.1, 2, 3, 4, 5, 6, 7
B.2, 1, 4, 3, 6, 5, 7
C.1, 3, 2, 5, 4, 7, 6
D.2, 3, 4, 5, 6, 7, 1

答案 B

解析

根据题目算法,就是相邻的两个指针交换值,p开始指向第一个元素,q指向p的下一个元素,交换第一和第二元素值,两个数交换完,p = q->next也就是第三个元素,q = p->next指向第四元素,交换第三和第四元素的值,while循环依次交换知道指向末尾

image-20230105093230642

2023.1.6

错题9

下列程序的运行结果是PP 10003,请为横线处选择合适的程序( )

#include <stdio.h>
#include <string.h>

struct STU {
    char name[10];
    int num;
};

void f(char _____, int num) {
    struct STU s[2] = {{"SS", 10001}, {"PP", 10002}};
    num = s[1].num;
    strcpy(name, s[1].name);
}

main() {
    struct STU s[2] = {{"YY", 10003}, {"LL", 10004}}, *p;
    p = s;
    f(p->name, p->num);
    printf("%s %d\n", p->name, p->num);
}
A.*name
B.name[]
C.name
D.&name

答案 AB

解析

传入函数的应为指向字符串的首地址的指针,这样在函数体内才可以修改字符串的内容。故a正确。

数组名作为函数形参时,会退化为指针,故B也正确。

C显然不对。

D 这样写 是一个char型变量的引用,不是字符串,如果写成char* &name应该就对了。

错题10

void main (void) {
    int i ;
    i = 0x10 + 010 + 10;
    printf ("x = %x", i); 
}

以上程序的输出是()

答案 22

解析

不同进制的表示:

二进制:0dXXXX

八进制:0XXXX

十六进制:0xXXXX

%x是以16进制输出

0x10为16,010为8,加10为34,表示为16进制为22。

错题11

对于下面代码片段,下面说法正确的是

myFile.open("Sales.dat", ios::app);
A.该文件只能用于输出
B.该文件只能用于输入
C.该文件既可以用于输出,也可以用于输人
D.若该文件存在,则清除该文件的内容

答案 A

解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFqmcAuz-1679561161426)(2023年1月.assets/image-20230106095406274.png)]

文件的输入输出是站在内存的角度,in——输入到内存,即从文件中读出;out——从内存输出,即写入到文件。选项的意思是该文件只能用于从程序中输出。

2023.1.7

错题12

下列函数定义中,有语法错误的是()

A.void fun(int x, int *y){*x *= *y;}
B.void fun(int *x, int y){*x += y;}
C.int * fun(int *x, int y){return x += y;}
D.void fun(int x, int *y){x *= *y;}

答案 A

解析 x *= *y表示x=x* *y,但是A中*x无意义

错题13

下面代码的运行结果为()

#include<iostream>
#include<string>
using namespace std;

class B0 {
public:
    virtual void display() {
        cout << "B0::display0" << endl;
    }
};

class B1 :public B0 {
public:
    void display() { cout << "B1::display0" << endl; }
};

class D1 : public B1 {
public:
    void display() { 
        cout << "D1::display0" << endl; 
    }
};

void fun(B0 ptr) {
    ptr.display();
}

int main() {
    B0 b0;
    B1 b1;
    D1 d1;
    fun(b0);
    fun(b1);
    fun(d1);
}
A.B0::display0 B0::display0 B0::display0
B.B0::display0 B0::display0 D1::display0
C.B0::display0 B1::display0 D1::display0
D.B0::display0 B1::display0 B1::display0

答案 A

解析

这里是按值传递,子类对象传递进来之后,发生了 对象切片 ,只保留基类对象部分,因此,调用只是会调用基类部分的函数

把 void fun(B0 ptr) 改为 void fun(B0 *ptr) 或 void fun(B0 &ptr)

结果是C. B0::display0 B1::display0 D1::display0

因为display函数在基类中被声明为虚函数后,它在派生类中将自动成为虚函数

2023.1.8

错题14

int main()
{
    char *p = "hello,world";
    return 0;
}

p和"hello,world"存储在内存哪个区域?

答案 堆,只读存储区

解析 动态分配的内存才存放在堆,比如new malloc,局部变量存放在栈,常量存放在只读存储区

错题15

在32位系统下下面程序输出的是?

#include<stdio.h>
union uni{
    int a;
    char b;
 };
struct str{
	int a;
    char b;
 };
int main(int argc, char **argv){
     printf("%d %d\n", sizeof(union uni), sizeof(struct str));
     return 0;
 }

答案 4 8

解析

union的大小取决于所占空间最大的变量的大小 int a32位占4字节,所以uni的大小就是4字节

struct的大小由于内存对齐问题,int a四个字节,char b虽然是1个字节 但是为了存取效率,char b也被分配了一块4字节的空间,所以整个结构体所占空间为8字节

2023.1.9

错题16

#include<iostream>
using namespace std;

class Base
{
public:
    virtual int foo(int x)
    {
        return x * 10;
    }

    int foo(char x[14])
    {
        return sizeof(x) + 10;
    }
};

class Derived: public Base
{
    int foo(int x)
    {
        return x * 20;
    }

    virtual int foo(char x[10])
    {
        return sizeof(x) + 20;
    }
} ;

int main()
{
    Derived stDerived;
    Base *pstBase = &stDerived;

    char x[10];
    printf("%d\n", pstBase->foo(100) + pstBase->foo(x));

    return 0;
}

在32位环境下,以上程序的输出结果是?

答案 2014

解释:pstBase->foo(100) + pstBase->foo(x)

pstBase->foo(100)  调用继承的函数,因为父函数有virtual修饰,被子类的同名函数覆盖。

pstBase->foo(x) 调用父类函数,因为 父函数没有有virtual修饰。int foo(char x[14]) 参数传的是指针,指针是4个字节。

所以结果是2014。

注意,看下面的例子,即使是形参传入数组也会退化为指针,在函数内对数组的修改在函数体外仍会实现。

void test(int x[])
{
    cout << x[1] << endl;
    x[1] = 0;
}
int main(int argc, char** argv) {
    int x[10];
    x[1] = 1;
    test(x);
    cout << x[1] << endl;
    return 0;
}
image-20230109094254719

错题17

下列程序编译时有语法错误的语句是()

#include<iostream>
#include<string>

using namespace std; 

class Pet {
     string name;
public:
     Pet(string p=" ") { name = p; }
     string getName() const { return name; }
     virtual void call() const=0;
};

class Dog : public Pet{
public:
    Dog(string n) : Pet(n) {}
    void call() const { cout<< "##" << " "; }
};

class Cat : public Pet{
public:
    Cat(string n) : Pet(n) {}
    void call() const { cout << "**"; }
};

void f(Pet *p) {
    p->call();
}
int main() { 
    Pet pet0("#");    //(1)
    Dog pet1("*");    //(2)
    Cat pet2("$");    //(3)
    f(&pet1);         //(4)
    f(&pet2);         //(5)
    return 0;
}

答案 (1)

解析

类 Pet 包含纯虚函数,是一个虚基类,不能直接实例化,因此注释 (1) 错误。A选项正确。(2) 和 (3)中 Dog 和 Cat 是派生类实例化没有问题。 (4) 和 (5) 可以将派生类对象指针转换为基类指针使用,因此也不会有问题。

2023.1.10

错题18

下面程序中, 输出是什么?

int fun(int x){
    int count = 0;
    while(x){
        count++;
        x = x &(x-1);
    }
    return count;
}
int main(){
    cout << "fun(2015)=" << fun(2015)<<endl;
}
A.fun(2015)=11
B.fun(2015)=10
C.fun(2015)=9
D.fun(2015)=8

答案 B

解析

&与运算符,只有当1&1时结果为1,其他均为0,可知此题为统计2015=11111011111中有多少个1。

错题19

以下程序的执行结果是:

#include <iostream>
using namespace std;
int i = 0;
int function(int n) {
    static int a = 2;
    a++;
    return a + n;
}
void main() {
    int k = 5;
    {
        int i = 2;
        k += function(i);
    }
    k += function(i);
    cout << k;
}

答案 14

解析 第二次的i是全局变量,等于0。

错题20

现在有以下语句,则执行后,变量sz的值将得到

struct _THUNDER {
    int iVersion;
    char cTag;
    char cAdv;
    int iUser;
    char cEnd;
} Nowcoder;
int sz = sizeof(Nowcoder);

答案 16

解析 补齐8

错题21

以下程序的输出结果为( )

using namespace std;
void print(char **str){
    ++str;
    cout<<*str<<endl;
}
int main() {
    static char *arr[]={"hello", "world", "c++"};
    char **ptr;
    ptr=arr;
    print(ptr);
    return 0;
}
A.hello
B.world
C.字符w的起始地址
D.字符e

答案 B

解析

可以把 *ptr当作一个整体,指向一个char* 的字符串,然后注意下面这些情况:

*ptr = arr[0] = "hello"
(*ptr)[1] = arr[0][1] = 'e'
(*ptr + 1) = arr[0][1:] = "ello"
*(ptr + 1) = arr[1] = "world"

错题22

关于C++中的友元函数说法正确的是( )

A.友元函数需要通过对象或指针调用
B.友元函数是不能被继承的
C.友元函数没有this指针
D.友元函数破环了继承性机制

答案 BC

2023.1.31

错题23

#include <iostream>
 
using namespace std;
class A {
  public:
    virtual void print() {
        cout << "A::print()"
             << "\n";
    }
};
 
class B : public A {
  public:
    virtual void print() {
        cout << "B::print()"
             << "\n";
    }
};
 
class C : public A {
  public:
    virtual void print() {
        cout << "C::print()"
             << "\n";
    }
};
 
void print(A a) { a.print(); }
int main() {
    A a, *aa, *ab, *ac;
    B b;
    C c;
    aa = &a;
    ab = &b;
    ac = &c;
    a.print();
    b.print();
    c.print();
    aa->print();
    ab->print();
    ac->print();
    print(a);
    print(b);
    print(c);
}

上面代码的输出是?

A::print() B::print() C::print() A::print() B::print() C::print() A::print() A::print() A::print()

解析:

虚函数会具有动态绑定功能,会按照实际类型调用相关的函数。
1, a.print(); b.print(); c.print();
分别输出A::print() B::print() C::print(),
2,aa->print(); ab->print(); ac->print();
由于是虚函数,所以输出实际对象类型对应的print,因此输出A::print() B::print() C::print(),
3,void print(A a){ a.print();}函数声明的形参为A类型的,相当于强制类型转换,因此调用print(A a)函数的输出都是A::print()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦想广东收租

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值