题目摘录-编程语言(C++)(二)
题目:
某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)均为指针。
题目:
在C++中,
const int i = 0;
int *j = (int *) &i;
*j = 1;
printf("%d, %d", i, *j);
输出是多少?
答案:
0
1
解答:
考察C++常量折叠。
1. const变量放在编译器的符号表中,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化。
2. 结论,const变量通过取地址方式可以修改该地址存储的数据值,但不能修改常量的值。
题目:
下列代码的输出为:
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. 虚函数表地址被清空。
题目:
有哪几种情况只能用intialization list而不能用assignment?
答案*:
当类中含有const成员变量;基类无默认构造函数时,有参的构造函数都需要初始化表;当类中含有reference成员变量。
解答:
1. 见答案。
题目:
对以下数据结构中data的处理方式描述正确的是:
struct Node{
int size;
char data[0];
};
答案:
编译器会认为这就是一个长度为0的数组,而且会支持对于数组data的越界访问。
解答:
考察柔性数组。
1*. 柔性数组,作为占位符放在结构体末尾,使得结构体的大小动态可变,在声明结构体变量的时候可根据需要动态分配内存。
2. 长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代表了一个不可修改的地址常量。
3. 常用于网络通信中构造不定长数据包,不会浪费空间浪费网络流量。
题目:
给定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。
题目:
若有以下定义和语句:
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'部分。
题目:
以下函数用法正确的个数是:
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'。
题目:
假设在一个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字节元素,只装入一半。
题目:
请选择下列程序的运行结果:
#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类型的临时变量,只拷贝基类部分数据(只有指向基类虚函数表的虚函数指针)。