C++语言基础题-----持续补充

C++语言基础题-----持续补充,第1张

C++语言基础题-----持续补充

1.

以下变量分配在BSS段的是()

1

2

3

4

5

6

7

char s1[100];

int s2 = 0;

static int s3 = 0;

void main() {

    char s4[100];

}

A,s1                                 B,s2                    C,s3                       D,s4

BSS段:通常是指用来存放程序中未初始化的全局变量的一块内存区域;

数据段:通常是指用来存放程序中 已初始化 的 全局变量 的一块内存区域,static意味着在数据段中存放变量;

代码段:通常是指用来存放 程序执行代码 的一块内存区域;

堆:存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减,这一块在程序运行前就已经确定了;

栈:栈又称堆栈, 存放程序的 局部变量 (不包括static声明的变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。

正确答案:A

2.

以下程序的输出结果为________________.

1

2

3

4

5

6

7

8

9

10

#include

#define ADD(x)  x*x

main( )

{  int a=4,b=6,c=7,d=ADD(a+b)*c;

printf("d=%d",d);

}

宏定义只是简单的文本替换,并不会进行运算的优先级。

#define ADD(x)  x*x

int main( )

int a=4,b=6,c=7,d=ADD(a+b)*c;

printf("d=%d",d);

//ADD(a+b)*c=x*x*c=4+6*4+6*7=70;

}

.就是简单的替换

3.

1

2

3

4

5

6

7

#include "stdio.h"

int main() {

    int a = 8, b;

    b = a|1;

    b >>= 1;

    printf("%d,%dn", a, b);

}

上面的C程序段的输出为__________.

C语言中|是按位或的意思,a可以表示为00001000,1表示为00000001,因此b为00001001,>>表示右移一位,因此b为00000100,即为4

答案:8 4.

4.

在 32 位编译器上,设有定义

1

char *str1 = "Hello", str2[] = "Hello"; 

则以下语句

1

 printf("%d %d", sizeof(str1), sizeof(str2)); 

的输出结果是____________.

解析:

这题非常有趣

所谓的有趣不是题目考核的sizeof的知识

而是两个字符串的存储位置是不同的

考虑如下示例代码:

1

2

    char *a = "Hello", b[] = "Hello";

    printf("%p %pn",a, b);

可得以下输出:

0x100000faa 0x7fff5fbff742

可见两者虽看似指向相同的数据

实际上却有着完全不同的内存表现

b所处的0x7fff5fbff742就是函数堆栈

所以当函数结束后这个字串就会被抛弃

事实上本着能省则省的原则

编译器不会去销毁它,只是让他留在内存中称为脏数据罢了

你无法对其寻址,并且这段内存随时可以被新的入栈数据覆盖

而a所处的0x100000faa是个全局的区域

让我们对题目中的代码反编译

可得到汇编代码

截取以下有效信息:

1

2

3

    .section    __TEXT,__cstring,cstring_literals

L_main.b:                               ## @main.b

    .asciz  "Hello"

可以看到a指向的字符串被保存在了__TEXT段的__cstring节

这个节的性质是用于存储cstring_literals也就是C语言的字符串字面值类型

这里的.asciz就是说明"Hello"是一个C语言的字符串字面值类型

其地址偏移则表示为标记L_main.b

汇编里就通过这个标记对"Hello"字串进行寻址

存储在__cstring中的字符串字面值可以复用

也就是说相同的指向"Hello"都指向L_main.b这个"Hello"

这样就提升了空间效率

5.

下面这段程序的输出是什么?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#include

class A{

    public:

        A(){ p(); }

        virtual void p(){ printf("A"); }

        virtual ~A(){ p(); }

};

class B:public A{

    public:

        B(){ p(); }

        void p(){ printf("B"); }

        ~B(){ p(); }

};

int main(int, char**){

        A* a = new B();

        delete a;

}

解析:

构造函数和析构函数是无法实现多态性的。理由是:

1.构造函数中,先构造父类,再构造子类,父类构造函数中调用函数,此时子类还没有构造,怎么实现多态性?

2.析构函数中,先析构子类,再析构父类。当我们在一个类中执行析构函数时,它的派生类都已经析构了,自然无法实现多态性。

所以答案就是:ABBA

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5651643.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存