1.在32位小端的机器上,如下代码输出是什么:
char array[12] = {0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08};
short *pshort = (short *)array;
int *pint = (int *)array;
int64 *pint64 = (int64 *)array;
printf("0x%x , 0x%x , 0x%llx , 0x%llx", *pshort , *(pshort+2) , *pint64 , *(pint+2));
A、0x201 , 0x403 , 0x807060504030201 , 0x0
B、0x201 , 0x605 , 0x807060504030201 , 0x0
C、0x201 , 0x605 , 0x4030201 , 0x8070605
D、0x102 , 0x506 , 0x102030405060708 , 0x0
解答:小端存储规则:数据的高位存放在高地址,数据的低位存放在低地址。
① char——一个字节
存储形式:
数据 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 |
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
② short——两个字节
存储形式:
数据 | 0x0201 | 0x0403 | 0x0605 | 0x0807 |
下标 | 0 | 1 | 2 | 3 |
*pshort从下标0开始,所以为0x201;
*(pshort+2)从下标2开始,所以为0x605;
③ int64——八个字节
存储形式:
数据 | 0x0807060504030201 |
下标 | 0 |
*pint64从下标0开始,所以为0x807060504030201;
④ int——四个字节
存储形式:
数据 | 0x04030201 | 0x08070605 |
下标 | 0 | 1 |
*(pint+2)从下标2开始,下标最大为1,后面默认补零,所以为0x0.
2.下面描述中,表达错误的是:
A、公有继承时基类中的private成员在派生类中仍是private
B、公有继承时基类中的public成员在派生类中仍是public
C、公有继承时基类中的protected成员在派生类中仍是protected
D、私有继承时基类中的public成员在派生类中是private
解答:
-
公有继承是指派生类继承基类的 public、protected 成员,而基类的 private 成员在派生类中是不可访问的。公有继承关系中,基类的 public 成员可以在任何地方被访问,派生类的成员函数也可以访问基类的 protected 成员,但不能访问基类的 private 成员。
-
私有继承是指派生类继承基类的 public、protected 成员,但它们都变成了派生类的 private 成员,而基类的 private 成员在派生类中仍然是不可访问的。私有继承关系中,基类的成员在外界都无法访问,只有派生类的成员可以访问,但这些成员通过派生类对象也无法访问基类的成员。
-
保护继承是指派生类继承基类的 public、protected 成员,但它们都变成了派生类的 protected 成员,而基类的 private 成员在派生类中仍然是不可访问的。保护继承关系中,基类的 public 成员只能在派生类的成员函数和友元函数中被访问,基类的 protected 成员可以在派生类的成员函数和友元函数中被访问,但不能在外界被访问,基类的 private 成员在派生类中仍然是不可访问的。
3.关于引用以下说法错误的是:
A、引用必须初始化,指针可以不初始化
B、引用初始化以后不能被改变,而指针可以改变指向
C、不存在指向空值的引用,但是存在指向空值的指针
D、一个引用可以看作是某个变量的一个“别名”
E、引用传值,指针传地址
F、函数参数可以声明为引用或指针类型
解答:
指针和引用区别 | 指针和引用联系 |
指针是一个变量,它存储另一个变量的内存地址。通过指针,我们可以访问或修改存储在特定内存位置的数据。 | 指针和引用都可以用来操作内存地址,但它们的本质是不同的:指针是一个独立的对象,而引用是原对象的别名。 |
引用是变量的一个别名,它在声明时必须初始化,并且一旦与某个变量绑定后,就不能再改变其引用的对象。 |
4、下列关于new delete 与malloc free 的联系与区别描述正确的有:
A、都是在栈上进行动态的内存操作
B、用malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会自动调用对象的构造函数
C、delete 会调用对象的destructor,而free 不会调用对象的destructor
D、以上说法都不正确
解答:
A:new/delete 和 malloc/free 都是用于在堆(heap)上进行动态内存操作,而不是栈(stack)上。
(1)栈(stack)是由编译器自动管理的一块内存区域,用于存储函数调用时的局部变量、函数参数和返回地址等。栈上的内存分配和释放是自动完成的,无需手动管理。
(2)堆(heap)是由程序员手动进行内存分配和释放的一块内存区域,用于存储动态分配的对象、数组等。在堆上分配内存需要使用 new(C++)或 malloc(C)等操作符/函数,而释放内存则需要使用 delete(C++)或 free(C)操作符/函数。
5、 定义宏
则DECLARE(val, int)替换结果为:
A、int val_int_type
B、int val_int_int
C、int name_int_int
D、int name_int_name
解答:
在C++中,可以使用预处理指令#define来定义宏。宏是一种文本替换机制,它允许在代码中定义一个标识符,当编译器遇到该标识符(标识符可以是任何有效的标识符名称)时,会将其替换为预定义的文本(替换文本可以是任何合法的C++代码片段)。
宏的基本语法:
#define 标识符 替换文本
#define PI 3.14159 // 定义常量宏
#define MAX(a, b) ((a) > (b) ? (a) : (b)) // 定义带参数的宏函数
#define SQUARE(x) ((x) * (x)) // 定义带参数的宏表达式
##是一种分隔连接方式,它的作用是先分隔,然后进行强制连接,宏定义中使用##时,预处理器会将宏定义中的##替换为相应的标识符。
#define CONCAT(a, b) a##b
int main() {
int var12 = 42;
int result = CONCAT(var, 12); // 将var和12连接成一个标识符var12
cout << result << endl; // 输出42
}
“name”和第一个“_”之间被分隔了,所以预处理器会把name##_##type##_type解释成4段:“name”、“_”、“type”以及“_type”,name和type会被替换,而_type不会被替换。
有任何问题欢迎留言!