题目摘录-编程语言(C++)(二)

题目摘录-编程语言(C++)(二)

Question 11 :

题目:
    某32位系统下, C++程序,请计算sizeof 的值:
    char str[] = "http://www.xxxxx.com";
    char *p = str;
    int n = 10;
    sizeof(str) = (1);
    sizeof(p) = (2;
    sizeof(n) = (3);
    void Foo(char str[100]){
        sizeof(str) = (4);
    }
    void *p = malloc(100);
    sizeof(p) = (5);

答案:
    21
    4
    4
    4
    4

解答:
    考察sizeof返回值。
    1. 具体类型,返回该类型所占的空间大小。
    2. 对象,返回对象的实际占用空间大小。
    3. 数组,返回编译时分配的数组空间大小(数组名 ≠ 指针)。作为参数时数组退化为指针。
    4. 指针,返回存储该指针所用的空间大小。
    5. 函数,返回函数的返回类型所占的空间大小。函数的返回类型不能是void。
    6. 上题中(2)(4)(5)均为指针。

Question 12* :

题目:
    在C++中,
    const int i = 0;
    int *j = (int *) &i;
    *j = 1;
    printf("%d, %d", i, *j);
    输出是多少?

答案:
    0
    1

解答:
    考察C++常量折叠。
    1. const变量放在编译器的符号表中,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化。
    2. 结论,const变量通过取地址方式可以修改该地址存储的数据值,但不能修改常量的值。

Question 13 :

题目:
    下列代码的输出为:
    class parent{
    public:
        virtual void output();
    };
    void parent::output(){
        printf("parent!");
    }
    class son : public parent{
    public:
        virtual void output();
    };
    void son::output(){
        printf("son!");
    }
    son s;
    memset(&s, 0, sizeof(s));
    parent& p = s;
    p.output();

答案:
    没有输出结果,程序运行出错。

解答:
    考察memset和虚函数指针。
    1. 虚函数表地址被清空。

Question 14 :

题目:
    有哪几种情况只能用intialization list而不能用assignment?

答案*:
    当类中含有const成员变量;基类无默认构造函数时,有参的构造函数都需要初始化表;当类中含有reference成员变量。

解答:
    1. 见答案。

Question 15* :

题目:
    对以下数据结构中data的处理方式描述正确的是:
    struct Node{
        int size;
        char data[0];
    };

答案:
    编译器会认为这就是一个长度为0的数组,而且会支持对于数组data的越界访问。

解答:
    考察柔性数组。
    1*. 柔性数组,作为占位符放在结构体末尾,使得结构体的大小动态可变,在声明结构体变量的时候可根据需要动态分配内存。
    2. 长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代表了一个不可修改的地址常量。
    3. 常用于网络通信中构造不定长数据包,不会浪费空间浪费网络流量。

Question 16 :

题目:
    给定3个int类型的正整数x,y,z,对如下4组表达式判断正确的选项:
    int a1 = x + y - z; int a2 = x - z + y;
    int b1 = x * y / z; int b2 = x / z * y;
    int c1 = x << y >> z; int c2 = x >> z << y ;
    int d1 = x & y | z; int d2 = x | z & y;

答案:
    a1一定等于a2

解答:
    考察对变量运算原理的了解。
    1. 加减操作虽然可能出现溢出,但相同操作数的不同顺序只是中间结果不同,最终结果相同。
    2. int类型做除法可能会造成截断,比如3/2 = 1。
    3. 移位运算可能会丢弃超出的位数。有符号数二进制数1111 1111,先左移2位再右移三位为1111 1111,反之1111 1100。

Question 17 :

题目:
    若有以下定义和语句:
    char s1[] = "12345", *s2 = "1234";
    printf("%d\n", strlen(strcpy(s1, s2)));
    则输出结果是:

答案:
    4

解答:
    考察strcpy和strlen。
    1. 首先strlen得到的是'\0'之前的字符长度。
    2. strcpy将s2指向的字符串'1234\0'全部拷贝到s1指向位置并覆盖其'12345'部分。

Question 18 :

题目:
    以下函数用法正确的个数是:
    void test1(){
        unsigned char array[MAX_CHAR + 1], i;
        for(i = 0;i <= MAX_CHAR; i++){
            array[i] = i;
        }
    }

    char *test2(){
        char p[] = "hello world";
        return p;
    }
    char *p = test2();

    void test3(){
        char str[10];
        str++;
        *str = '0';
    }

答案:
    0

解答:
    考察数组名和指针区别。
    1. i的范围有可能超过unsigned char范围。
    2. 这里char p[] = "hello world"是数组,该数组是临时变量,函数结束后不能继续使用。
    3. 如果为char *p = "hello world",这里p是指针并指向常量区字串,虽然p会被销毁,但字符串仍然在,就不会出问题。
    4. 这里str是数组名,数组名是常量,不可以自增,正确的操作是char *p = str; p++; *p = '0'。

Question 19* :

题目:
    假设在一个32位little endian的机器上运行下面的程序,结果是多少?
    #include <stdio.h>
    int main(){
        long long a = 1, b = 2, c = 3;
        printf("%d %d %d\n", a, b, c);
        return 0;
    }

答案:
    1
    0
    2

解答:
    考察小端法及printf输出控制符。
    1. long long占8字节。
    2. 小端表示,低字节在低位,最低4字节为1,接下来四字节为高位部分的0,再接下来4字节为第二个数低位的2。
    3. printf的控制符相当于分配好待打印容器大小,这里"%d %d %d"就分配了12字节,分别装入三个8字节元素,只装入一半。

Question 20 :

题目:
    请选择下列程序的运行结果:
    #include<iostream>
    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);
    }

答案:
    B0::display0
    B0::display0
    B0::display0
解答:
    1. 这里传递的是对象本身而非指针,对象被直接转为基类对象,调用基类的函数。
    2. 如果要实现虚函数动态绑定需要将B0 ptr改为B0* ptr,ptr->display()。
    3. 对象的形参传递需要先使用拷贝构造函数(默认)生成B0类型的临时变量,只拷贝基类部分数据(只有指向基类虚函数表的虚函数指针)。

猜你喜欢

转载自blog.csdn.net/weixin_38337616/article/details/88345217
今日推荐