文章目录
前言
我们先提出一个问题:既然程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名才能使用这段存储空间?
#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语言中一种特别的变量
指针所保存的值是内存的地址
可以通过指针修改内存中的任意地址内容
图示: