C/C++之指针入门


一、指针与变量

1.取地址符&和取值符*

(1)&

int a;
cout<<&a<<endl;
//0x6ffe4c
 
char b[10];
cout<<&b<<endl;
//0x6ffe40

(2)*

int n=6;
int *p=&n;
cout<<*p<<endl;
//6

(3)进阶

char c='a';
char *p=&c;
 
//c的值 
cout<<c<<endl;                                 //a 
 
//存储c变量名的地址
cout<<hex<<(long long)&c<<endl;                //6ffe3f
 
//存储p变量名的地址 
cout<<&p<<endl;                                //0x6ffe40
 
//p变量的值是p指针指向的地址,可以看出这是存储c变量名的地址
cout<<hex<<(long long)p<<endl;                 //6ffe3f
 
//p指针指向的对象的值 
cout<<*p<<endl;                                //a

2.定义指针

(1)定义一个指针

一步到位:类型* 指针名 = &变量名

int n=6;
int *p=&n;
cout<<p<<endl;
//0x6ffe44

分步进行:类型* 指针名;指针名=&变量名

int n=6;
int *p;
p=&n;
cout<<p<<endl;
//0x6ffe44

(2)定义多个指针

int n=6,m=7;
int *p,*q;
//都要有* 
p=&n,q=&m;
cout<<*p<<" "<<*q<<endl;
//6 7

3.通过指针修改值

int n=10;;
int *p=&n;
*p=6;
printf("%d %d\n",n,*p); 
//6 6

4.指针传递

(1)一级指针

改变传递的指针的值:可以传递改变

int n=5;
int *p=&n;
int *q=p;
printf("%d %d %d\n",n,*p,*q); 
//5 5 5
*q=3;
printf("%d %d %d\n",n,*p,*q);
//3 3 3

改变传递的指针的指向 :不可以传递改变

int n=3,m=5;
int *p=&n;
int *q=p;
printf("%d %d %d %d\n",n,m,*p,*q);
//3 5 3 3
q=&m;
printf("%d %d %d %d\n",n,m,*p,*q); 
//3 5 3 5

(2)二级指针

规则同一级指针

改变传递的指针的值:

注意:下面*q=&m代表改变指针的值,它的实际意义是改变指针p指向的地址。

int n=3,m=5;
int *p=&n;
int **q=&p;
printf("%d %d %d %d\n",n,m,*p,**q);
//3 5 3 3
*q=&m; 
//取值改变,但意义是*q==p,p=&m,改变p的指向 
printf("%d %d %d %d\n",n,m,*p,**q);
//3 5 5 5

改变指针的指向:

int n=3,m=5,z=10;
int *p=&n;
int *x=&z;
int **q=&p;
printf("%d %d %d %d\n",n,m,*p,**q);
//3 5 3 3
q=&x;
printf("%d %d %d %d\n",n,m,*p,**q);
//3 5 3 10

5.函数传参

定义void vex(int *q),以及调用时vex§,其实就是int *q=p;

#include<iostream>
using namespace std;
 
void vex(int *q)
{
    *q=6;
}
 
int main()
{
    int n=10;;
    int *p=&n;
    vex(p);
    cout<<n<<endl;
    //6
    return 0; 
}

例子:通过指针来交换a和b的值

#include<iostream>
using namespace std;
 
void swap(int *p,int *q)
{
    int temp=*p;
    *p=*q;
    *q=temp;
}
 
int main()
{
    int a=3,b=4;
    int *p=&a,*q=&b;
    swap(p,q);
    cout<<a<<" "<<b<<endl;
    //4 3 
    return 0; 
}

二、数组与指针

1.n等同于&n[0]

int n[10]={1,2,3,4,5};
int *p=n;
//其实就是int *p=&n[0]。这是数组的隐式转换
//当然写成int *p=&n[0]也对。 
cout<<*p<<endl;
//1
 
//完整写法 
int *q=&n[1];
cout<<*q<<endl;
//2
int m[10],n[10];
 
int i1=&m[5]-&m[3];			//指针或下标的减法,地址的值除以sizeof(int) 
cout<<&m[5]<<' '<<&m[3]<<endl;
//0x6ffdf4 0x6ffdec
cout<<i1<<endl;
//2
cout<<0x6ffdf4-0x6ffdec<<endl;
//8
 
int i2=&m[5]-&n[3];			//无意义,每次实现都不确定 
cout<<i2<<endl;
//-10 
 
int*p1=m+5;		//即p1=&m[5]
int*p2=m-5;		//无意义 
cout<<p1<<' '<<p2<<endl;
//0x6ffdf4 0x6ffdcc

2.指针遍历数组

int n[]={1,10,100};
int *p=n;
p++;
cout<<*p<<endl;
//10
//通常一起写作 cout<<*(++p)<<endl; 
//注意:不要写成cout<<*(p++)<<endl; 你需要的是指针移位后的结果
*px++*(px++)*++px或*(++px)(*px)++++(*px)++*px

int n[]={1,2,3,4};
for(int *p=n;p<(n+4);p++)    //p<(n+4)也可以写成p<&n[4]
{
    cout<<*p<<" ";
}
//1 2 3 4

3.char指针等效于数组(注意:指针名和数组名一样)

(1)都可以通过使用指针的算术运算或数组索引来访问数组

int n[10]={1,2,3,4};
for(int i=0;i<4;i++)
{
    cout<<n[i]<<" ";
}
//1 2 3 4
 
for(int *p=n;p<(n+4);p++)
{
    cout<<*p<<" ";
}
//1 2 3 4

(2)指针和数组并不是完全互换的

将数组名变量以指针的形式使用

int n[10]={1,2,3,4};
cout<<*n<<endl;
//1 可以使用

把指针运算符 * 应用到 n 上是完全可以的,但修改 n 的值是非法的(n++就是n=n+1,n被用在左值出现在等于号左边了)。这是因为 n 是一个指向数组开头的常量,不能作为左值。

int n[10]={1,2,3,4};
for(int i=0;i<4;i++)
{
    cout<<*n<<" ";
    n++; 
}
//error

只要不改变数组的值,仍然可以用指针形式的表达式。

int n[10]={1,2,3,4};
for(int i=0;i<4;i++)
{
    *(n+i)=6; 
    cout<<n[i]<<endl;
}

(3)与函数

这六个函数就是为了说明指针和数组完全可以互化,除了(2)的n++情况。

#include <iostream>
#include <string.h>
using namespace std;
 
void vex1(char *p)
{
	for(int i=0;i<strlen(p);i++)
	{
		cout<<p[i];
	}
	cout<<endl;
}
 
void vex2(char *p)
{
	cout<<p<<endl;
}
 
void vex3(char *p)
{
	for(int i=0;i<strlen(p);i++)
	{
		cout<<*(p+i);
	}
	cout<<endl;
}
 
 
void vex4(char t[])
{
	for(int i=0;i<strlen(t);i++)
	{
		cout<<t[i];
	}
	cout<<endl;
}
 
void vex5(char t[])
{
	char *p=t;
	cout<<p<<endl;
}
 
void vex6(char t[])
{
	for(int i=0;i<strlen(t);i++)
	{
		cout<<*(t+i);
	}
	cout<<endl;
}
 
 
 
int main()
{
	char *s={"thanks"};
	vex1(s);
	vex2(s);
	vex3(s);
	
	cout<<endl;
	
	char t[]={"sorry"};
	vex4(t);
	vex5(t);
	vex6(t);
	return 0;
}
/*
thanks
thanks
thanks
sorry
sorry
sorry
*/

4.字符串数组与指针

strlen()内可以使用字符串数组,也可以使用指向字符串的指针。(必须是char类型的,如strlen(int数组)就报错)

注意:p和*p。p输出字符串,*p输出单个char。

char n[10]={"thanks"};
char *p=n;
cout<<strlen(n)<<endl;
//6
cout<<strlen(p)<<endl;
//6
cout<<p<<endl;
//thanks
cout<<*p<<endl;
//t
cout<<*++p<<endl;
//h

ps:char[] 与int []的区别 :

int[] 通过指针输出的是地址,char[] 通过指针输出的是字符串。

int n[]={1,2,3,4};
int *p=n;
cout<<p<<endl;
//0x6ffe30

5.int二维数组传参

数组调用形式函数传参含义函数传参时维度指定数值可更改?
int a[10][10]a(int a[10][10])同样规模的数组指定两个维度可更改
int a[10][10]a(int a[][10])可以省略第一维,但第二维不能省指定第二维可更改
int a[10][10]aint (&a)[10][10]二维数组的引用指定两个维度可更改
int a[10][10]aint (*a)[10]一维数组指针指定第二维可更改
int a[10][10](int**)a,m,nint **a,m,n强制转换为指针的指针需要附加传入m行n列可更改

(1)参数int a[10][10]

#include <iostream>
using namespace std;
 
void vex(int a[10][10]){
	cout<<a[0][0]<<endl;
	//1
	a[0][0]=6;
}
 
int main() {
	// your code goes here
	int a[10][10];
	a[0][0]=1;
	vex(a);
	cout<<a[0][0]<<endl;
	//6
	return 0;
}

(2)参数int a[][10]

#include <iostream>
using namespace std;
 
void vex(int a[][10]){
	cout<<a[0][0]<<endl;
	//1
	a[0][0]=6;
}
 
int main() {
	// your code goes here
	int a[10][10];
	a[0][0]=1;
	vex(a);
	cout<<a[0][0]<<endl;
	//6
	return 0;
}

(3)参数int (*a)[10]

#include <iostream>
using namespace std;
 
void vex(int (*a)[10]){
	cout<<a[0][0]<<endl;
	//1
	a[0][0]=6;
}
 
int main() {
	// your code goes here
	int a[10][10];
	a[0][0]=1;
	vex(a);
	cout<<a[0][0]<<endl;
	//6
	return 0;
}

(4)参数int (&a)[10][10]

#include <iostream>
using namespace std;
 
void vex(int (&a)[10][10]){
	cout<<a[0][0]<<endl;
	//1
	a[0][0]=6;
}
 
int main() {
	// your code goes here
	int a[10][10];
	a[0][0]=1;
	vex(a);
	cout<<a[0][0]<<endl;
	//6
	return 0;
}

(5)参数int **a

#include <iostream>
using namespace std;
 
//m行n列
void vex(int **a,int m,int n) {
	
	//cout << a[0][0] << endl;
	//使用int **时,对于a[0][0],编译器不能正常寻址。
 
	cout << *((int *)a+n*1+2) << endl;
	//8
	//*((int *)a+n*i+j),i行j列
 
	*((int*)a) = 6;
 
}
 
int main() {
	// your code goes here
	int a[2][5] = {1,2,3,4,5,6,7,8,9,10};
	//这是强制转化
	vex((int**)a, 2, 5);
	cout << a[0][0] << endl;
	//6
	
	return 0;
}

三、指针数组int *n[5]和数组指针int (*n)[5]

1.int *n[5]是指针数组

int *n[5]:包含5个int *类型的指针的数组,是一个数组。

PS:把类型结合起来看,int *表示指针,[5]表示五个,所以就是5个int *类型的指针的数组。

PS:指针数组-指针的数组

存放在栈中

int a=1,b=2;
int *p[2];
p[0]=&a,p[1]=&b;
cout<<*p[0]<<" "<<*p[1];
//1 2

对于局部变量,标准的编译器会被释放掉的(比如ideone.com),但有些编译器却不会(VScode和Visual Studio2019)。
但对于vector类型,都会被释放掉

#include <iostream>
using namespace std;
 
int main()
{
    int* p[2];
    {
        int a = 1, b = 2;
        p[0] = &a, p[1] = &b;
    }
    cout << *p[0] << " " << *p[1];
    //0 0(ideone)
    //1 2(VS和VScode)
    
    return 0;
}

存放在堆中

#include <iostream>
using namespace std;
 
int main()
{
	int* p[2];
	p[0] = new int(1);
	p[1] = new int(2);
	cout << *p[0] << " " << *p[1];
	//1 2
	return 0;
}

2.int(*n)[5]是数组指针

int (*n)[5]:表示一个指针,该指针指向一个int型有5个元素的数组。

PS:*和n被()包围起来,那么类型就只是int,所以就是一个指向int数组的指针。

PS:数组指针-数组的指针

//int (*b)[5]用来指向列元素个数为5的二维数组
 
int a[2][5] = { {1,2,3,4,5},{6,7,8,9,10} };
int(*b)[5] = a;
//int (*b)[n]的n是和int a[m][n]的n对应相等。
 
 
//a可以理解为两个一位数组嵌套,外层是包含两个元素的一维数组,外层是包含五个元素的一维数组。
 
cout << *(*(b)) << endl;
//1
cout << *(*(b+1)) << endl;
//6
cout << *(*(b)+1) << endl;
//2
cout << b[0][2] << endl;
//3

四、指针与const

*前面的是对被指向对象的修饰,*后面的是对指针本身的修饰

1.常量指针

格式:int const* p;或 const int* p;

记法:(常量:int const或const int)*指针

又叫常指针,可以理解为常量的指针,指向的是个常量。所以不可以通过指针来修改指向的对象。。

int x=6;
const int* p = &x;  //或const int* p;p=&x;
p = &y;             //可以,修改指针的指向
*p = 123;           //错误,不可以通过指针修改x的值
x = 666;            //可以,可以直接修改x的值

2.指针常量

格式:int* const p;

记法:(指针*)常量

修饰的是指针,指针指向不可以改变,说明指针是常量,所以叫指针常量。

不可以修改指针指向,但可以通过指针修改内存空间的值。

int* const p = &x;   //必须初始化赋值,int* const p;报错
p = &y;              //错误,不可以修改指针的指向
*p = 123;            //正确,但可以通过指针修改内存空间的值。

3.const int * const p;

既修饰了指针,也修饰了内存空间,都不可以修改

const int * const pp = &x;
pp = &y;             //错误
*pp = 123//错误

五、动态数组

1.一维动态数组

(1)下标赋值取值

#include <iostream>
using namespace std;
 
int main() {
	int n;
	cin >> n;
	int* a = new int[n];
	for (int i = 0; i < n; i++) {
		a[i] = i;
		cout << a[i] << ' ';
	}
	delete a;
	return 0;
}
/*
5
0 1 2 3 4
*/

(2)指针赋值取值

#include <iostream>
using namespace std;
 
int main() {
	int n;
	cin >> n;
	int* a = new int[n];
	for (int i = 0; i < n; i++) {
		*(a + i) = i;
		cout << *(a + i) << ' ';
	}
	delete a;
	return 0;
}
/*
5
0 1 2 3 4
*/

2.二维

https://blog.csdn.net/zhanshen112/article/details/80758850


参考:

https://www.cnblogs.com/zhangrxiang/p/8647602.html

https://bbs.csdn.net/topics/60157289

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值