网站建设指导,ui培训完找工作没人要,龙口网页设计,云主机安装wordpress面试题9#xff1a;什么是内存地址
内存地址是指计算机内存中存储变量或对象的地址。内存空间大小就是寻址能力#xff0c;即能访问到多少个地址#xff0c;比如 32 位机器内存空间大小就是 2^32 4294967296#xff0c;也就是 4 GB 。每个变量或对象在内存中都有一个唯一…面试题9什么是内存地址
内存地址是指计算机内存中存储变量或对象的地址。内存空间大小就是寻址能力即能访问到多少个地址比如 32 位机器内存空间大小就是 2^32 4294967296也就是 4 GB 。每个变量或对象在内存中都有一个唯一的地址通过该地址可以访问和操作该变量或对象。注意一 个内存地址对应一个字节以 int 类型的变量为例其占据 4 个内存地址其中首个内存地址就是这个变量的地址。
#include iostreamint main()
{int vals[4]{};printf(val1 address %p\n, vals[0]);printf(val2 address %p\n, vals[1]);printf(val3 address %p\n, vals[2]);printf(val4 address %p\n, vals[3]);return 0;
}上面代码的输出为
val1 address 0000005420F6F978
val2 address 0000005420F6F97C
val3 address 0000005420F6F980
val4 address 0000005420F6F984为了能够说明 1 个 int 类型的变量占据 4 个内存地址我们在上面的代码中使用占据连续内存的数组来做测试由这个输出可以看出数组 vals 的第一个元素所占据的内存地址由 0000005420F6F978 到 0000005420F6F97B 再往下的一个地址就是第二个元素的首地址 0000005420F6F97C刚好是 4 个内存地址其首个内存地址 0000005420F6F978 就是这个数组 vals 的第一个元素的地址同时也是这个数组变量 vals 的地址。
面试题10常量指针与指针常量的区别
常量指针const pointer和指针常量pointer to const是两个不同的概念常量指针指的是其指向变量的值不可改变但是指针本身是可以改变的可以指向其他变量指针常量指的是指针本身是常量其不可以再指向其他变量。 常量指针的样例代码
const int val1 1;
int *ptr1 val1; //错误必须使用常量指针
const int *ptr1 val1; //OK
*ptr1 2; 指针常量的样例代码
int val1 1;
int val2 2;
int const *ptr1 val1; //OK
*ptr1 val2; //错误指针本身是常量其不可以再指向其他变量。面试题11野指针出现的原因
野指针出现的原因主要有以下三种 1指针变量未初始化。局部指针变量的默认值是一个随机值如果此时访问该指针则会引起程序崩溃。所以指针变量在创建的同时应当被初始化要么将指针设置为 nullptr 要么让它指向合法的内存 new 出来的对象或者现有的一个对象。 2释放内存后没有将指针设置为 nullptr 。不管是 free 还是 delete 在释放内存时只是把指针所指的内存给释放掉了但此时指针的值依然是之前内存空间的首地址。此时访问该指针则会引起程序崩溃。 3指针操作超越变量作用范围。栈内存在函数结束时会被释放如果将其内存地址通过指针返回给调用者此时再访问则会引起程序崩溃。
面试题12使用 nullptr 的好处是什么
nullptr 关键字是在 C11 标准中引入的用于表示空指针。在 C11 及以后的版本中nullptr 替代了 C98/03 中的 NULL 或 0 作为空指针的表示。该关键字可以避免函数重载问题如下为样例代码
void overLoadFunc(int* val);
void overLoadFunc(int val);int main()
{overLoadFunc( NULL ); // 期待调用 overLoadFunc(int* val); 但实际调用却是 overLoadFunc(int val);
}上面代码中的 overLoadFunc( NULL ); 实际调用的是 overLoadFunc(int val); 。其原因是 NULL 本身就是整数 0 因此进入了整型参数的重载函数。
面试题13什么是指针的指针
指针的指针是一个指向指针的指针。指针可以指向所有数据类型的变量基本类型、结构体类型、类类型等而指针自身也是一种变量所以指针自然也可以指向指针。指针的指针通常用于处理二维数组、动态分配的二维数组或处理指针数组等。 如下样例可以帮助理解指针的指针
#include iostreamint main()
{int val1 1;int *ptr1 val1;int **ptr2 ptr1;printf(ptr1 address %p\n, ptr1);printf(ptr1 address %p\n, (*ptr2));printf(ptr2 value %p\n, ptr2);return 0;
}上面代码的输出为
ptr1 address 000000C4A839F758
ptr1 address 000000C4A839F758
ptr2 value 000000C4A839F758由结果可以看出指向指针的指针变量 ptr2 保存了指针变量 ptr1的地址 000000C4A839F758 。 其中代码第 10 行 int **ptr2 ptr1; 定义了一个指向指针的指针这里用了两个星号*其保存的值就是指针变量 ptr1的地址。 第 11、 12、 13 行代码尤为重要 第 11 行代码 printf(ptr1 address %p\n, ptr1); 其中的 ptr1 是对指针变量 ptr1 做取地址操作。 第 12 行代码 printf(ptr1 address %p\n, (*ptr2)); 其中的 (*ptr2) 是对指针变量 ptr2 做解引用操作再对其做取地址操作相当于直接对指针变量 ptr1 做取地址操作。 第 13 行代码 printf(ptr2 value %p\n, ptr2); 对指向指针的指针取值直接用其变量名即可。 使用指针的指针来处理二维数组时其对应内存的创建以及释放都需要使用循环 1创建二维数组
int** vals new int*[2];
for (size_t i 0; i 2; i)
{vals[i] new int[3]();
}2释放二维数组的内存
int** vals new int*[2];
for (size_t i 0; i 2; i)
{vals[i] new int[3]();
}for (size_t i 0; i 2; i)
{delete[] vals[i]; //注意 delete 一定要加上中括号 []
}这里尤其注意 delete[] 的使用。