【C/C++】:指针(Pointer)

1 指针和常量的区别:

指针常量和常量指针的区别:https://www.cnblogs.com/lizhenghn/p/3630405.html

1.空指针

在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。

NULL 指针是一个定义在标准库中的值为零的常量。请看下面的程序:

实例

#include <iostream>

using namespace std;

int main ()
{
    
    
   int  *ptr = NULL;

   cout << "ptr 的值是 " << ptr ;
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

ptr 的值是 0
在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。

如需检查一个空指针,您可以使用 if 语句,如下所示:

if(ptr) /* 如果 ptr 非空,则完成 /
if(!ptr) /
如果 ptr 为空,则完成 */
因此,如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针。很多时候,未初始化的变量存有一些垃圾值,导致程序难以调试。

2.指针数组

把 ptr 声明为一个数组,由 MAX 个整数指针组成。因此,ptr 中的每个元素,都是一个指向 int 值的指针。下面的实例用到了三个整数,它们将存储在一个指针数组中,如下所示:

实例

#include <iostream>
 
using namespace std;
const int MAX = 3;
 
int main ()
{
    
    
   int  var[MAX] = {
    
    10, 100, 200};
   int *ptr[MAX];
 
   for (int i = 0; i < MAX; i++)
   {
    
    
      ptr[i] = &var[i]; // 赋值为整数的地址
   }
   for (int i = 0; i < MAX; i++)
   {
    
    
      cout << "Value of var[" << i << "] = ";
      cout << *ptr[i] << endl;
   }
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200

3.指向指针的指针

指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。
指针的指针就是将指针的地址存放在另一个指针里面。
通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
在这里插入图片描述

#include <iostream>
 
using namespace std;
 
int main ()
{
    
    
    int  var;
    int  *ptr;
    int  **pptr;
 
    var = 3000;
 
    // 获取 var 的地址
    ptr = &var;
 
    // 使用运算符 & 获取 ptr 的地址
    pptr = &ptr;
 
    // 使用 pptr 获取值
    cout << "var 值为 :" << var << endl;
    cout << "*ptr 值为:" << *ptr << endl;
    cout << "**pptr 值为:" << **pptr << endl;
 
    return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:

var 值为 :3000
*ptr 值为:3000
**pptr 值为:3000

4 传递指针给函数

C++ 允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。

#include <iostream>
using namespace std;
 
// 函数声明
double getAverage(int *arr, int size);
 
int main ()
{
    
    
   // 带有 5 个元素的整型数组
   int balance[5] = {
    
    1000, 2, 3, 17, 50};
   double avg;
 
   // 传递一个指向数组的指针作为参数
   avg = getAverage( balance, 5 ) ;
 
   // 输出返回值
   cout << "Average value is: " << avg << endl; 
    
   return 0;
}
 
double getAverage(int *arr, int size)
{
    
    
  int    i, sum = 0;       
  double avg;          
 
  for (i = 0; i < size; ++i)
  {
    
    
    sum += arr[i];
   }
 
  avg = double(sum) / size;
 
  return avg;
}

5.函数返回指针

必须声明一个返回指针的函数,如下所示:

int * myFunction()
{
    
    
.
.
.
}

另外,C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static变量。

//生成 10 个随机数,并使用表示指针的数组名(即第一个数组元素的地址)来返回它们
#include <iostream>
#include <ctime>
#include <cstdlib>
 
using namespace std;
 
// 要生成和返回随机数的函数
int * getRandom( )
{
    
    
  static int  r[10];
 
  // 设置种子
  srand( (unsigned)time( NULL ) );
  for (int i = 0; i < 10; ++i)
  {
    
    
    r[i] = rand();
    cout << r[i] << endl;
  }
 
  return r;
}
 
// 要调用上面定义函数的主函数
int main ()
{
    
    
   // 一个指向整数的指针
   int *p;
 
   p = getRandom();
   for ( int i = 0; i < 10; i++ )
   {
    
    
       cout << "*(p + " << i << ") : ";
       cout << *(p + i) << endl;
   }
 
   return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:

624723190
1468735695
807113585
976495677
613357504
1377296355
1530315259
1778906708
1820354158
667126415
*(p + 0) : 624723190
*(p + 1) : 1468735695
*(p + 2) : 807113585
*(p + 3) : 976495677
*(p + 4) : 613357504
*(p + 5) : 1377296355
*(p + 6) : 1530315259
*(p + 7) : 1778906708
*(p + 8) : 1820354158
*(p + 9) : 667126415

2.&和*区别

指针是指向变量的地址
&:获取变量的地址
一元运算符
: 返回位于操作数所指定地址的变量的值
*
简单的例子分析:

int main()
{
    
    
	int a = 3;
	int *b = &a;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	*b = 10;
	cout << "&a:" << &a << endl;
	cout << "b:" << b << endl;
	cout << "a=" << &a << endl;
	system("pause");
}

结果:
a:3
b:00EFFE28
&a:00EFFE28
b:00EFFE28
a=10

**b是a的指针,指向a的地址。(也就是a与b相连,只要修改*b的值,a的值也跟着改动)**

3.类和指针

https://blog.csdn.net/keneyr/article/details/89364275
https://www.jianshu.com/p/a75b267325c2

void指针

void指针是没有类型.任何指针都可以赋值给void指针 ,不用转换,只需要地址而不需要长度,不能判断指向对象长短的指针 , void *vp; int *p; vp=p;

但是void指针赋值给其他类型的指针时都要进行类型转换 ,类型转换的目的是获得指向变量/对象大小 type p=(type)vp;

void指针不能解引用 的 *vp//错误 因为void指针只知道,指向变量/对象的起始地址 ,而不知道指向变量/对象的大小(占几个字节)所以无法正确引用。

void指针不能参与指针运算,除非进行转换 (type*)vp++; //vp==vp+sizeof(type)

void * 和 void 在函数返回值中的区别在:
函数的返回值中, void 是没有任何返回值, 而 void * 是返回任意类型的值的指针.

4 通过函数返回指针和数组

函数通过函数返回指针

#include <iostream>

using namespace std;

void splitfloat(int *x,int *y)//形参x,y为指针
{
    
    

	int x1 = 1;
	int y1 = 100;

	*x = y1 + x1;
	*y = y1 - x1;
}


int main()
{
    
    
	int n=0, f=0;
	splitfloat(&n, &f);  //变量地址作为实参
	cout << "n:" << n << endl;
	cout << "f:" << f << endl;

函数通过函数返回指针和数组
test.h文件

#ifndef TEST_H_
#define TEST_H_

int a[4][2];
int x0;

#endif

.cpp文件

#include <iostream>
#include "test.h"

using namespace std;

void splitfloat(int *x)       //形参x为指针
{
    
    
	
	int x1 = 1;
	int y1 = 100;
	for (int m = 0; m < 4; m++)
	{
    
    
		for (int n = 0; n < 2; n++)
		{
    
    

			a[m][n] = m+x1;
			cout << "a[" << m << "]" << "[" << n << "]:" << a[m][n] << endl;
			x1 += 1;
		}
	}
	
	//for (int i = 0; i < 4; i++)
	//{
    
    
	//	x0 = x1 + i;
	//	
	//}
	//	//*x = x1 + i;
	//	
	//	*x = x0;
		
}



int main()
{
    
    
	int n=0,f=0;

	//int a[4][2] = {0};
	

	splitfloat(&n);  //变量地址作为实参
	
	cout << "a[0][0]:" << a[0][0] << endl;
	cout << "a[0][1]:" << a[0][1] << endl;
	cout << "a[1][0]:" << a[1][0] << endl;
	cout << "a[1][1]:" << a[1][1] << endl;
	cout << "a[2][0]:" << a[2][0] << endl;
	cout << "a[2][1]:" << a[2][1] << endl;
	cout << "a[3][0]:" << a[3][0] << endl;
	cout << "a[3][1]:" << a[3][1] << endl;
	/*for (int j = 0; j < 4; j++)
	{
		for (int k = 0; k < 2; k++)
		{
			cout << "a[" << j << "]" << "[" << k << "]:" << a[j][k] << endl;
		}
	}*/
	//cout << "f:" << f << endl;
	/*cout << "a[0]:" << a[0] << endl;
	cout << "a[1]:" << a[1] << endl;
	cout << "a[2]:" << a[2] << endl;
	cout << "a[3]:" << a[3] << endl;*/
}

5.指针的动态内存分配

指针数组的动态内存分配:


#include <iostream>

using namespace std;

int main()
{
    
    
  // 开始为二维的动态数组设置内存容量
	
	int **test2 = new int *[5];
	for (int j = 0; j < 5; j++)
	{
    
    
		test2[j] = new int [3];
	}

	for (int i = 0; i < 5; i++)
	{
    
    
		for (int k = 0; k < 3; k++)
		{
    
    
			test2[i][k] = i + k;
		}
	}

	for (int i = 0; i < 5; i++)
	{
    
    
		for (int k = 0; k < 3; k++)
		{
    
    
			cout << "test2[i][k]" << test2[i][k] << "\n";
		}
	}

	// 释放内存
	for (int k = 0; k < 3; k++)
	{
    
    
		delete[] test2[k];
	}
	delete[] test2;

	return 0;
}



类指针的动态内存分配:

#include <iostream>
using namespace std;

class Box
{
    
    
public:
	Box() {
    
    
		cout << "调用构造函数!" << endl;
	}
	int test() {
    
    
		cout << "调用test()函数!" << endl;
		return 0;
	}
	~Box() {
    
    
		cout << "调用析构函数!" << endl;
	}
};

int main()
{
    
    
	cout << "1调用析构函数!" << endl;
	Box *myBoxArray = new Box;
	cout << "2调用析构函数!" << endl;
	int result = myBoxArray->test();
	cout << "3调用析构函数!" << endl;
	delete myBoxArray; // 删除数组
	cout << "4调用析构函数!" << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44322778/article/details/123221681