C/C++指针讲解
2018-04-01 10:37
267 查看
指针是一种数据类型
指针变量
指针是一种数据类型,占用内存空间,用来保存内存地址。void test01() { int* p1 = 0x1234; int*** p2 = 0x1111; printf("p1 size:%d\n",sizeof(p1)); printf("p2 size:%d\n",sizeof(p2)); //指针是变量,指针本身也占内存空间,指针也可以被赋值 int a = 10; p1 = &a; printf("p1 address:%p\n", &p1); printf("p1 address:%p\n", p1); printf("a address:%p\n", &a); }
野指针和空指针
空指针
标准定义了NULL指针,它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针为NULL,可以给它赋值一个零值。为了测试一个指针百年来那个是否为NULL,你可以将它与零值进行比较。对指针解引用操作可以获得它所指向的值。但从定义上看,NULL指针并未执行任何东西,因为对一个NULL指针因引用是一个非法的操作,在解引用之前,必须确保它不是一个NULL指针。
如果对一个NULL指针间接访问会发生什么呢?结果因编译器而异。
不允许向NULL和非法地址拷贝内存:
void test() { char *p = NULL; //给p指向的内存区域拷贝内容 strcpy(p, "1111"); //err char *q = 0x1122; //给q指向的内存区域拷贝内容 strcpy(q, "2222"); //err }
野指针
在使用指针时,要避免野指针的出现:野指针指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。
什么情况下回导致野指针?
指针变量未初始化
任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
指针释放后未置空
有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。
指针操作超越变量作用域
不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。
void test() { int* p = 0x001; //未初始化 printf("%p\n",p); *p = 100; }
操作野指针是非常危险的操作,应该规避野指针的出现:
初始化时置 NULL
指针变量一定要初始化为NULL,因为任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的。
释放时置 NULL
当指针p指向的内存空间释放时,没有设置指针p的值为NULL。delete和free只是把内存空间释放了,但是并没有将指针p的值赋为NULL。通常判断一个指针是否合法,都是使用if语句测试该指针是否为NULL。
间接访问操作符
通过一个指针访问它所指向的地址的过程叫做间接访问,或者叫解引用指针,这个用于执行间接访问的操作符是*。注意:对一个int*类型指针解引用会产生一个整型值,类似地,对一个float*指针解引用会产生了一个float类型的值。
int arr[5]; int *p = * (&arr); int arr1[5][3] arr1 = int(*)[3] &arr1
在指针声明时,* 号表示所声明的变量为指针
在指针使用时,* 号表示操作指针所指向的内存空间
*相当通过地址(指针变量的值)找到指针指向的内存,再操作内存
*放在等号的左边赋值(给内存赋值,写内存)
*放在等号的右边取值(从内存中取值,读内存)
//解引用 void test01() { //定义指针 int* p = NULL; //指针指向谁,就把谁的地址赋给指针 int a = 10; p = &a; *p = 20;//*在左边当左值,必须确保内存可写 //*号放右面,从内存中读值 int b = *p; //必须确保内存可写 char* str = "hello world!"; *str = 'm'; printf("a:%d\n", a); printf("*p:%d\n", *p); printf("b:%d\n", b); }
指针的步长
指针是一种数据类型,是指它指向的内存空间的数据类型。指针所指向的内存空间决定了指针的步长。指针的步长指的是,当指针+1时候,移动多少字节单位。思考如下问题:
int a = 0xaabbccdd; unsigned int *p1 = &a; unsigned char *p2 = &a; //为什么*p1打印出来正确结果? printf("%x\n", *p1); //为什么*p2没有打印出来正确结果? printf("%x\n", *p2); //为什么p1指针+1加了4字节? printf("p1 =%d\n", p1); printf("p1+1=%d\n", p1 + 1); //为什么p2指针+1加了1字节? printf("p2 =%d\n", p2); printf("p2+1=%d\n", p2 + 1);
指针的意义_间接赋值
间接赋值的三大条件
通过指针间接赋值成立的三大条件:2个变量(一个普通变量一个指针变量、或者一个实参一个形参)
建立关系
通过 * 操作指针指向的内存
void test() { int a = 100; //两个变量 int *p = NULL; //建立关系 //指针指向谁,就把谁的地址赋值给指针 p = &a; //通过*操作内存 *p = 22; }
如何定义合适的指针变量
void test() { int b; int *q = &b; //0级指针 int **t = &q; int ***m = &t; }
间接赋值:从0级指针到1级指针
int func1(){ return 10; } void func2(int a) { a = 100; } //指针的意义_间接赋值 void test02() { int a = 0; a = func1(); printf("a = %d\n", a); //为什么没有修改? func2(a); printf("a = %d\n", a); } //指针的间接赋值 void func3(int* a) { *a = 100; } void test03() { int a = 0; a = func1(); printf("a = %d\n", a); //修改 func3(&a); printf("a = %d\n", a); }
间接赋值:从1级指针到2级指针
void AllocateSpace(char** p) { *p = (char*)malloc(100); strcpy(*p, "hello world!"); } void FreeSpace(char** p) { if (p == NULL) { return; } if (*p != NULL) { free(*p); *p = NULL; } } void test() { char* p = NULL; AllocateSpace(&p); printf("%s\n",p); FreeSpace(&p); if (p == NULL) { printf("p内存释放!\n"); } }
间接赋值的推论
用1级指针形参,去间接修改了0级指针(实参)的值。用2级指针形参,去间接修改了1级指针(实参)的值。
用3级指针形参,去间接修改了2级指针(实参)的值。
用n级指针形参,去间接修改了n-1级指针(实参)的值。
指针做函数参数
指针做函数参数,具备输入和输出特性:输入:主调函数分配内存
输出:被调用函数分配内存
输入特性
void fun(char *p /* in */) { //给p指向的内存区域拷贝内容 strcpy(p, "abcddsgsd"); } void test(void) { //输入,主调函数分配内存 char buf[100] = { 0 }; fun(buf); printf("buf = %s\n", buf); }
输出特性
void fun(char **p /* out */, int *len) { char *tmp = (char *)malloc(100); if (tmp == NULL) { return; } strcpy(tmp, "adlsgjldsk"); //间接赋值 *p = tmp; *len = strlen(tmp); } void test(void) { //输出,被调用函数分配内存,地址传递 char *p = NULL; int len = 0; fun(&p, &len); if (p != NULL) { printf("p = %s, len = %d\n", p, len); } }
相关文章推荐
- C++中字符串以及数组和指针的互相使用讲解
- 详细的讲解C/C++指针和内存问题的文章
- c++指针讲解 经典
- 【C/C++和指针】深入讲解位运算
- GetMemory错误讲解(指针练习)----C++面试之GetMemory问题
- 【C/C++和指针】深入讲解位运算
- C++中虚函数、虚表、虚指针实例讲解
- C++的多态性实现机制剖析(即VC视频第3课this指针讲解)
- 讲解C++ 7 种智能指针
- C++一级指针和二级指针做参数传递讲解
- C++的多态性实现机制剖析(即VC视频第3课this指针讲解)[程序员之家论坛]
- c++用指针交换数组的实例讲解
- 浅析C++中的智能指针
- C++中cout输出字符型指针地址值的方法
- c++指针相等的问题
- 从零开始学C++之类与对象:类声明、类作用域、前向声明、this指针、嵌套类、PIMPL 技法 等
- 王桂林讲C++之指向类成员指针
- C++中智能指针如何设计和使用
- paip.指针 引用 c++ java的使用总结.
- C++学习笔记,指针变量的引用与引用的指针