做外账要登什么网站,企业所得税怎么缴纳,周口建设公司网站,罗湖网站建设价格目录
前言
指针基础
指针实战
数组与指针比较
sizeof、strlen与指针
指针
函数传递指针的时候是副本
指针要分配给足够的空间
指针定义描述
this指针 前言
在我的博客C高质量编程-CSDN博客内存管理章节里面讲了一些内存的基础知识#xff0c;内存管理涉及最多的就是…目录
前言
指针基础
指针实战
数组与指针比较
sizeof、strlen与指针
指针
函数传递指针的时候是副本
指针要分配给足够的空间
指针定义描述
this指针 前言
在我的博客C高质量编程-CSDN博客内存管理章节里面讲了一些内存的基础知识内存管理涉及最多的就是指针也详细讲解了指针的原理以及平时编程使用指针犯的错误不太熟悉的可以去看看现在就对面试问的比较多的关于指针的问题归纳总结一下希望对看到这篇博客的同学们有所帮助。
指针基础
1.什么是指针请简述指针的基本概念和用途。
2.指针变量和普通变量有什么区别如何声明和初始化指针变量
3.指针的算术运算有哪些请举例说明
4.什么是野指针如何避免野指针的产生
5.指针和引用区别
6.什么是函数指针请简述函数指针的概念和用途
7.如何声明和初始化函数指针如何通过函数指针调用函数
8.什么是多级指针请举例说明多级指针的使用场景。
9.指针和数组有何关系如何通过指针访问数组元素
10.动态内存分配有哪些方式请简述它们的区别和用途
11.如何使用new和delete操作符进行动态内存分配和释放
12.C和C分别怎么动态分配内存有什么区别
13.什么是内存泄漏如何避免内存泄漏
14.请解释C中的const指针和指向cons指针的区别。
15.什么是智能指针请简述智能指针的概含和用途。
16.如何使用std:unique_ptr、std::shared_ptr和std:weak_ptr智能指针
指针实战
1.数组与指针比较
char szTest1[] 123;
char szTest2[] 123;
const char szTest3[] 123;
const char szTest4[] 123;
const char *pTest1 123;
const char *pTest2 123;
char *pTest3 123;
char *pTest4 123;
cout(szTest1szTest2)endl; //1 , 输出 0
cout(szTest3szTest4)endl; //2 , 输出 0
cout(pTest1pTest2)endl; //3 输出 1
cout(pTest3pTest4endl; //4 输出 1
szTest1、szTest2、szTest3、szTest4都是数组分配新空间它们有各自的内存空间这样写szTest1代表的数组的首地址因此szTest1、szTest2、szTest3、szTest4都不相同
pTest1、pTest2、pTest3、pTest4都是指针指定的地址都相同所以4个都是相同因此输出是0 0 1 1
2.sizeof、strlen与指针
char szTest1[] hello world;
const char* pTest1 hello world;
int len1 sizeof(szTest1);
int len2 strlen(szTest1);
int len3 sizeof(pTest1);
int len4 strlen(pTest1);
cout len1;//输出 12
cout len2;//输出 11
cout len3;//输出 8
cout len4;//输出 11
szTest1是数组以\0结尾sizeof计算内存占用空间所以输出12strlen计算字符串的长度字符串以\0结尾结束所以输出11pTest1是个指向const char的指针指针在x64下固定是8个字节所以输出是8strlen(pTest1是计算pTest1指向的字符串长度故输出11。
int calcLen(char str[])
{return (int)(sizeof(str)-1);//无论何时都是返回3
}
当函数传递的是数组指针的时候就自动退化为指针了 而指针的长度为4减去1就是3
3.指针
int m[5] { 4, 12, 241, 33, 545 };
int *ptr (int *)(m 1);
printf(%d,%d, *(m 1), *(ptr - 1));
理解指针运算”1“就是偏移量的问题一个类型为T的指针移动是以sizeof(T)为单位移动的。m1:在数组首元素地址的基础上偏移一个sizeof(a[0])单位。因此m1就代表数组第1个元素为2
m1在数组首元素的基础上偏移一个sizeof(m)单位m其实就是一个数组指针类型为int[5]。因此m1实际上是偏移了5个元素的长度也就是m5再看ptr是int类型因此ptr-1就是减去sizeof(int*)即为m[4]5;
m是数组首地址也就是m[0]的地址m1是数组下一个元素的地址即m[1]m是对象的首地址m1是下一个对象的地址即m[5]
4.函数传递指针的时候是副本
void GetMemory(char *p)
{pnew char[100];strcpy(p,hello world);
}
void main(void)
{char *strNULL;GetMemory(str);coutstr;delete []str;strNULL;
}
初看函数逻辑一切都是那么理所当然。仔细看下这里的str是指char*的指针把str指针拷贝了一份传给函数GetMemory, GetMemory参数中的p和str不一样了所以在GetMemory中改变p不会影响到strmain函数中的str还是NULL如果在GetMemory要返回new出的地址那参数p必须为引用或双重指针双重指针代码如下
void GetMemory(char **p)
{*pnew char[100];strcpy(*p,hello world);
}
void main(void)
{char *strNULL;GetMemory(str);coutstr;delete []str;strNULL;
}
也可以用引用代码如下
void GetMemory(char* p)
{pnew char[100];strcpy(p,hello world);
}
void main(void)
{char *strNULL;GetMemory(str);coutstr;delete []str;strNULL;
}
5.指针要分配给足够的空间
void func()
{char b;char *p b;strcpy(p, hello world);coutp;
}
因为 char类型的a变量只拥有了一字节的空间但是hello拥有6字节的空间包含最后的\0,所以程序出现问题有可能崩溃因为strcpy的时候有可能把func的返回地址覆盖了函数调用返回不到上级函数出现异常。
6.指针定义描述
int *a[10]; 由于符号[]的优先级高于*, 所以a优先于[]结合a是一个数组数组的每个元素都是指向int的指针
int (*a)[10]; 由于符号()的优先级高于[]所以a优先于*结合a是一个指针执行int类型的数组
int (*a)(int); 首先a是一个指针去掉a的()部分就是 int (int)这不就是一个函数吗所以a是一个指向int(int)函数的指针即函数指针。
int (*a[10])(int);
分解1) int (int) 2) a[10] 3) *所以a是一个大小为10的数组数组的每个元素都是指针该指针指向一个函数该函数有一个整型参数并返回一个整型数。
int ((*a)[10])(int);
分解1) int (int) 2) [10] 3) *a所以a是一个指针指向大小为10的数组数组的每个元素都是函数该函数有一个整型参数并返回一个整型数。
7.this指针
下面看一道比较经典的题目
class MyTest {
public:void Test() {cout Test() endl;}
private:int m_a;
};int main()
{MyTest* p nullptr;p-Test();
}
上面的代码运行会出现异常吗答案是不会。
原因分析1不管是C语言的函数还是C得成员函数都有一个准确的地址 2 在main函数中p调用Test函数的时候指针p会通过汇编寄存器ecx传给函数Test的入口参数 3 进入函数Test后这个ecx就赋值给this指针可以通过this指针访问MyTest类中的成员变量和成员函数。
上面代码MyTest类中Test函数中虽然this指针是空的但是函数里面也没有访问任何成员函数和成员变量所以不会报错。如果把题目改为如下
class MyTest {
public:void Test() {cout m_a endl;}
private:int m_a;
};int main()
{MyTest* p nullptr;p-Test();
}
运行报错原因是Test函数中的this指针是空的一旦访问m_a就提示访问内存报错。
如果还有不明白的同学可以去翻翻看深入理解C对象模型这本书把C对象模型讲的比较深比较透。
参考
C高质量编程-CSDN博客
深入理解C对象模型