C++指针1

1.指针的概念

用来存储数据的各个内存位置都有地址,地址给PC硬件提供了引用数据的途径。指针变量存储特定类型的另一个变量的地址。

2.声明指针

指针的声明和变量的声明一样。下面这段代码是指针声明的两种写法。
#include <iostream>
int main()
{
	using namespace std;
	//第一种
	long* num1;
	//第二种
	long *num2;
	return 0;
}

为了良好的 编程习惯我们一般倾向于第一种写法,因为num1是指向long类型的指针。星号离类型近一些意思更加清楚

在看一下下面这段代码:

#include <iostream>
int main()
{
	using namespace std;
	long* num1,num2;
	return 0;
}

这里不要误解为是声明了两个指针,其实num1 是指针,num2只是一个long类型的变量而已。

所以,一般我们把声明指针和声明变量分开成两行写

3.使用指针

3.1为什么要使用指针

1.指针可以直接操作内存中的数据,免除了在大数据块中使用变量操作还得赋值,可以提高效率
2.指针可以解决一个函数只有一个返回值,但我们需要同时又多个值改变等问题

 3.2指针的初始化

#include <iostream>
int main()
{
	using namespace std;
	int num=9;
	int* pNum=&num;
	return 0;
}

如上 是指针的初始化操作,采用的是&取址运算符

如果我们不想初始化为具体变量的地址,也可以采用如下方式
#include <iostream>
int main()
{
	using namespace std;
	int* pNum=nullptr;
	if (!pNum)
	{
		cout<<"num1 does not point to anything"<<endl;
	}
	return 0;
}

	
nullptr是C++11中的一个新特性,如果不支持,可以将nullptr改写为NULL或0。

NULL其实是0的一个宏定义,我们知道布尔类型,0即假非0即真 因此 不管是使用NULL 0 还是nullptr都可以隐世转换为bool

为什么会出现nullptr呢?? 因为使用0初始化执行会引起歧义,,到底指针是不是执行0所在的地址,还是指针是空 搞不清

3.3指针的使用

3.3.1 指针的基本使用方法

下面是指针的简单使用方法:
#include <iostream>
int main()
{
	using namespace std;
	long* pNumber=nullptr;
	long number1=55,number2=99;

	//将number1的地址赋给pNumber   此时pNumber指向number1
	pNumber=&number1;
	//*pNumber是55,+11即66,此时*pNumber和number1的值是66
	*pNumber+=11;
	//输出 number1=66 &number1=其内存地址,这个地址每次运行都会变的
	cout<<"number1= "<<number1<<" &number1= "<<pNumber<<endl;

	//改变指针的引用  *pNumber=99
	pNumber=&number2;
	//number1=99*10  即number1=990
	number1=*pNumber*10;
	//输出 number1=990 &number1=其内存地址 *pNumber=99
	cout<<"number1= "<<number1<<" &number1= "<<pNumber<<" *pNumber= "<<*pNumber<<endl;
	return 0;
}

	

3.3.2 指向char类型的指针

<pre name="code" class="cpp">#include <iostream>
int main()
{
	using namespace std;
	char* pStr="Hello Pointer";
	cout<<"pStr="<<pStr<<endl
		<<"*(pStr+1)="<<*(pStr+1)<<endl
		<<"*pStr="<<*pStr<<endl;
		
	return 0;
}

 这里输出的是: pStr=Hello Pointer     *(pStr+1)=e        *pStr=H 
这里的Hello Pointer字符串常量在内存中是以单个字符存放的,最后以\0结束,将它赋值给字符指针,其实是将首字母H的地址赋值给指针
此时指针*pStr就是首字母H   而后*(pStr+1)  等同于 char[1]  即 e   pStr就是整个字符串   ,可以把pStr看成是一个字符数组,更容易理解
#include <iostream>
int main()
{
	using namespace std;
	char pStr[]="Hello Pointer";
	cout<<"pStr="<<pStr<<endl
		<<"*(pStr+1)="<<*(pStr+1)<<endl
		<<"*pStr="<<*pStr<<endl;
		
	return 0;
}

	
和上面的代码意思一样

#include <iostream>
int main()
{
	using namespace std;
	char* pStr=new char[];
	//pStr="Hello Pointer";
	strcpy(pStr,"Hello Pointer");
	*pStr='D';
	cout<<pStr<<endl;
	return 0;
}

	

第六行和第七行,这里都是将字符串Hello Pointer赋值给指针,

但是,如果使用第六行进行赋值,然后再改变其值,会报错,其实是因为,通常系统将字符串常量存储在内存的一块只读区域,所以不能进行修改

这里还要注意,我们使用了new char[] 这是动态的再内存中分配一块内存区域,然后我们strcpy将字符串拷贝过来,这样才能修改里面的单个字符

还有一个模糊的概念,如下代码:
#include <iostream>
int main()
{
	using namespace std;
	char* pStr="Hello Pointer";
	cout<<sizeof(pStr)<<endl;
	cout<<sizeof(*pStr)<<endl;
	char arrayStr[]="Hello Pointer";
	cout<<sizeof(arrayStr)<<endl;
	cout<<sizeof(*arrayStr)<<endl;
	return 0;
}

	
输出:4 1  14  1

先前我们说pStr和ArrayStr的意义是一样的,其实这里还有一个细微的区别,sizeof(pStr)pStr其实也是一个变量,只是他存储的是其他变量的地址而已,所以这里是4

而sizeof(arrayStr) 得出的是数组中所以字符的字节大小总和,这里需要大家区分开来

3.4指针常量和常量指针

#include <iostream>
int main()
{
	using namespace std;
	int number=10,number2=20;
	//常量指针
	const int* pNumber=&number;
	//*pNumber=20;  //错误,常量指针所指向的值是不能修改的
	pNumber=&number2; //正确,常量指针可以改变其指向

	//指针常量
	int* const pNumber1=&number;
	*pNumber1=20; //正确,指针常量所指向的值可以修改
	//pNumber1=&number2; //错误,指针常量的指向不能改变
	return 0;
}

	
这里有点蒙,我们可以这样记

首先如何区分常量指针和指针常量, 我们可以把const 看做汉字常量 *可以看做指针 那个在前面就先读那个  

然后,如何记忆他们之间的区别呢?? 

把常量看做值,指针看做地址,哪个在前哪个就不能改变

总结:
区分是常量指针还是指针常量,就看const 和* 哪个在前哪个在后

区分常量指针和指针常量的区别,把常量看做值,指针看做地址,哪个在前哪个就不能改变

故,const int * pNumber=&number; const在前*在后 常量指针 常量在前 值不能改变

int* const pNumber=&number; *在前 const在后 指针常量 指针在前 地址不能改变


3.5获得字符指针所指向的字符串长度

#include <iostream>
int main()
{
	using namespace std;
	char* pChar="Hello World";
	cout<<strlen(pChar)<<endl;
	return 0;
}

	
这里和数组一样用了strlen,这是C++库函数,它的实现如下代码:
size_t __cdecl strlen (
        const char * str
        )
{
        const char *eos = str;

        while( *eos++ ) ;

        return( eos - str - 1 );
}
我们还可以采用递归:
#include <iostream>
int mystrlen(const char* temp)
{
	if (!temp||*temp=='\0')
	{
		return 0;
	}
	return mystrlen(temp+1)+1;
}
int main()
{
	using namespace std;
	char* pChar="Hello World";
	cout<<mystrlen(pChar)<<endl;
	return 0;
}

	





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值