C语言之指针基础

前言

我们先提出一个问题:既然程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名才能使用这段存储空间?

#include <stdio.h>
#include <malloc.h>

int main()
{
	int i = 5;
	int* p  = &i;

	printf("%d, %08x\n",i ,p);

	*p = 10;

	printf("%d, %08x\n",i ,p);
	
	return 0;
}

在这里插入图片描述
问题的答案很显然,不是,可以通过指针来使用这段存储空间。

指针本质:

指针在本质上也是一个变量
指针需要占用一定的内存空间
指针用于保存内存地址的值

不同类型的指针占用的内存空间大小相同吗?

#include <stdio.h>
#include <malloc.h>

int main()
{
	int* pI;
	char* pC;
	long* pL;
	double* pD;

	printf("%d\n",sizeof pI );
	printf("%d\n",sizeof pC );
	printf("%d\n",sizeof pL );
	printf("%d\n",sizeof pD );
	
	return 0;
}

在这里插入图片描述
在32位PC机上,指针占用的内存为4个字节。(为什么是4个字节哪?指针需要具备存储任意一个地址的能力。)

*号的意义:

在指针声明时,*号表示所声明的变量为指针;

在指针使用时,*号表示取指针所指向的内存空间中的值。

//指针声明:

int i = 0;

int j = 1;

int* p = &i;

//取值

j = *p;

指针在内存中图示:

在这里插入图片描述
* p就是:从0XAABBCCD0的地址开始,取4个字节的长度(int* p)。

代码实践:

指针是一种类型吗?指针类型!!!

#include <stdio.h>
#include <malloc.h>

int main()
{
	int i = 1;
	int*  pI;
	
	pI = &i;

	printf("%0x, %0x\n",pI, &i); //指针变量的值

	printf("%d, %d\n", sizeof(int*), sizeof(pI)); //可以写成sizeof(int*),说明int*为一种类型。

	printf("%0x\n",&pI); //指针变量的地址
	
	return 0;
}

运行结果:

在这里插入图片描述

通过指针写内存:

#include <stdio.h>
#include <malloc.h>

int main()
{
	int i = 1;
	int*  pI;
	
	pI = &i;

//	*((int*)0x62fe44) = 100; //注释① 可以看到,我们都可以直接通过指针写内存了!!!

	printf("%0x, %0x, %d\n",pI, &i, i);	
	
	return 0;
}

我们将上述代码在windows系统上运行(本处使用devcpp的IDE),多运行几次,可以发现:

第一次运行:

在这里插入图片描述
第二次运行:

在这里插入图片描述
连续运行多次,我们可以发现:int i变量的地址都为0x62fe44,我们现在利用Windows系统的这一特性做一个黑客操作(放开 注释①)。

运行结果:

在这里插入图片描述

传值调用和传址调用:

在这里插入图片描述

指针是变量,因此可以声明指针参数
当一个函数体内部需要改变实参的值,则需要使用指针参数
函数调用时实参值将复制到形参
指针适用于复杂数据类型作为参数的函数中

证明:“指针适用于复杂数据类型作为参数的函数中” 的demo:

#include <stdio.h>
#include <malloc.h>

struct Test
{
	int a[10000];
	int b[10000];
};

void f(struct Test t) //传值:copy 2000*4 个字节
{
	
}

int main()
{
	struct Test tt;
	f(tt);	
	
	return 0;
}
#include <stdio.h>
#include <malloc.h>

struct Test
{
	int a[10000];
	int b[10000];
};

void f(struct Test* t) //传址: 
{
	
}
int main()
{
	struct Test tt;
	f(&tt);	
	
	return 0;
}

代码实践:

利用指针实现变量交换函数:

通过宏:

#include <stdio.h>
#include <malloc.h>

 #define SWAP(a,b) { int t=a; a=b; b=t; } //宏是直接展开

int main()
{
	int i = 1;
	int j = 2;

	printf("i = %d, j = %d\n", i, j);

	SWAP(i,j);

	printf("i = %d, j = %d\n", i, j);
	
	return 0;
}

运行结果:
在这里插入图片描述

实现了交换的功能

写swap函数:(传值调用)

#include <stdio.h>
#include <malloc.h>

void swap(int a, int b)
{
	int t = a;
	a = b;
	b = t;
}

int main()
{
	int i = 1;
	int j = 2;

	printf("i = %d, j = %d\n", i, j);

	swap(i,j);

	printf("i = %d, j = %d\n", i, j);
	
	return 0;
}

运行结果:

在这里插入图片描述
没有实现了交换的功能

写swap函数:传址调用

#include <stdio.h>
#include <malloc.h>

void swap(int* a, int* b)
{
	int t = *a;
	*a = *b;
	*b = t;
}

int main()
{
	int i = 1;
	int j = 2;

	printf("i = %d, j = %d\n", i, j);

	swap(&i,&j);

	printf("i = %d, j = %d\n", i, j);
	
	return 0;
}

运行结果:

在这里插入图片描述
实现了交换的功能

常量与指针(const修饰指针):

const int* p; //p可变,p指向的内容不可变

int const* p; //p可变,p指向的内容不可变

int* const p; //p不可变,p指向的内容可变

const int* const p; //p和p指向的内容都不可变

口诀:

当const出现在 * 号左边时指针指向的数据为常量
当const出现在 * 后右边时指针本身为常量

指针小结:

指针是C语言中一种特别的变量

指针所保存的值是内存的地址

可以通过指针修改内存中的任意地址内容

图示:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/QQ1402369668/article/details/88105508