全面攻克指针

全面攻克指针

  • 前言
    • 指针是什么?
    • 指针如何使用?
      • 指针的定义
      • 指针的解引用
    • 指针的内存
    • 空指针和野指针
    • const修饰指针
      • const修饰指针
      • const修饰常量
      • const既修饰指针又修饰常量
    • 指针和数组
    • 指针进行地址传递改变实参
    • 结构体指针访问结构体变量/数组
    • 利用指针对结构体变量地址传递

前言

从大一学的c语言开始接触指针这样一个概念,到现在研一学习c++又遇到这样一个无法避开的概念,我决定把再次学习指针的一些粗浅理解记录下来,做一个整理。后续也会继续补充。

指针是什么?

我们知道在程序中声明一个变量之后,会分配给这个变量相应的内存空间,内存空间大小根据变量类型的不同也有差异。这个内存空间有其地址,变量的数据就存储在这个内存空间里。
指针它也是一个变量,它也有空间地址也有数据,而它的数据正是某个变量的地址,我们叫做指针指向变量地址。

指针如何使用?

指针的定义

int a=0;//定义一个变量,变量类型为整型
int * p=&a;//定义一个指针,指针指向a,格式为:数据类型 * 指针变量 =&被指变量 

指针的解引用

我们可以通过解引用(指针变量前加个*,即*p)来操作指针变量指向的内存。

*p =100;
cout<<*p<<"  "<

指针的内存

通过输入以下代码可以去显示出指针所占用多少内存

cout<

说下结论:32位操作系统的所有数据类型的指针占4个字节,64位操作系统的所有数据类型的指针占8个字节。
为什么不同位数操作系统的指针无论任何数据类型都是固定的呢? 32位操作系统的地址总线为32位,也就是有32位数字表示地址,而指针内存存储的就是地址,所以无论什么类型的指针它的所占内存空间都是32位,也就是4个字节。64位操作系统同理。

空指针和野指针

这两个指针指向的内存空间都不是我们申请的,所以不能访问,否则编译器会成功编译但是程序运行的时候会报错,提示访问权限冲突。下面看下这两个指针具体是怎样定义的。

//空指针指向内存地址编号为0的空间
//空指针一般用来初始化指针变量
int *p=NULL;

//野指针指向内存地址编号为0x1100的空间
int *p=(int *)0x1100;

const修饰指针

const修饰指针

const修饰指针叫做常量指针,在这种情况下*p无法操作,也就是说常量指针无法修改指针所指向的内存,但是可以修改指针的指向。

//常量指针
const int *p=&a;
*p=10;//报错,无法修改指针所指向地址的内存
p=&b;//正确,可以修改指针指向

const修饰常量

const修饰常量也叫做指针常量,在这种情况下,无法修改指针所指向的地址但是可以修改指针的所指向的空间的内存,和上面的常量指针正好相反。

//指针常量
int * const p=&a;
p=&b;//报错,不可以修改指针指向的地址
*p=10;//正确,可以修改指针指向的内存

const既修饰指针又修饰常量

在这种情况下,既不可以修改指针所指向的地址也不可以修改指针指向地址的内存。

//const既修饰指针又修饰常量
const int * const p=&a;//指针指向变量a,锁死!

指针和数组

这里我们说的数组是一维数组。我们知道数组名是数组的首地址,将指针指向首地址,再利用解引用就可以输出数组的第一个元素。
同时,需要知道的是指针自加1之后,在内存空间移动了多少个字节呢?这是根据指针类型有所不同的。int型指针自加1之后向后移动了4个字节,而char型指针自加1之后向后移动了1个字节,这样可以保证指针自加1之后所指向的是下一个元素。

int arr[5]={1,2,3,4,5};
int * p=char;//指针指向数组首地址
for(int i=0;i<5;i++)
{
cout<<*p<

指针进行地址传递改变实参

这里和之前学过的值传递对比,先将代码码出来

//定义交换函数,交换输入的参数指针a和b
void swap(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=*temp;
}
int main(){
int x=10,y=20;
int *p=&x;
int *q=&y;
swap(*p,*q);

cout<<"交换后的x与y分别为:"<

输出为

交换后的x与y分别为:20  10

结构体指针访问结构体变量/数组

结构体可以看做一种数据类型,这种数据类型里有多种常用的数据类型,我们定义一个结构体变量之后,多个结构体变量的集合就是结构体数组。但是归根到底,结构体变量是个变量,结构体数组也还是个数组,所以我们用指针访问结构体变量和结构体数组和前面的格式是一样的。

    //创建一个结构体变量
	struct student s1;
	//创建一个指针指向结构体变量
	struct student* q = &s1;
	q->age = 100;
	cout << s1.age << endl;
	
//创建一个结构体数组
	struct student arr[3]{
		{"张三",18,98},
		{"李四",18,97},
		{"王五",19,100}
	};
	//利用.访问结构体各个元素
	cout << arr[1].age << endl;
     //利用指针访问结构体元素
	//定义结构体指针并将其指向结构体数组,数组名为首个数组元素地址
	student* p = arr;
    //利用结构体指针以及->访问结构体变量
	cout << p->age << endl;
	p=p+2;
	cout << p->age << endl;

利用指针对结构体变量地址传递

前面学习过利用指针对变量进行地址传递,这里使用指针进行结构体变量地址传递是相同的原理,只不过数据类型变成了结构体。

//定义结构体
struct student {
	    string name;
		int age;
		int socre;
	};
	//定义一个打印函数,输入参数为指针
int printstu( student *p) {
	p->age = 100;
	cout << p->age << endl;
	return 0;
}
//创建一个结构体变量
struct student s1;
//将s1地址传入printstu()函数中
printstu(&s1);

可以看到结果就是将s1变量的age进行打印。

你可能感兴趣的:(c++,c语言,数据结构)