指针浅析
一. 指针是什么
指针是一个用来指示一个内存地址的计算机语言的变量或中央处理器(CPU)中的寄存器(Register)
二. 指针与内存地址
内存地址表示内存某特定单元
对于32位的操作系统来说,可表示的内存地址从0x0~0xFFFFFFFF。而指针因存储的是内存地址,所以32位的操作系统指针大小为4bit
C/C++用&就能取变量的地址,当然并不是所有的变量都有内存地址,如:
#include <stdio.h>
int main(void)
{
register int a; //a是寄存器变量
printf("%d",&a);
return 0;
}
这里会建议编译器把a存储于寄存器中,如果a存放在寄存器中,那么a是不能取到内存地址的,不过由于编译器的某些处理,有些编译器并不会对此报错,而是你对其取地址,他就会把这个变量存放在内存区域(vc++6.0)
三. 指针的简单应用
1. 指针与变量
#include <stdio.h>
int main(void)
{
int a = 10;
int *p; //p是一个指向整型的指针
p = &a; //把a的地址赋值给p
*p = 15; //修改p指向的地址位置的内容
printf("%10d %10d\n",&a,p); //p和&a是等价的,都是a的内存地址
printf("%10d %10d",a,*p); //a和*p是等价的,都是15,不过a是直接访问的,*p是先访问的p的地址,获取到a的地址,然后在访问a
return 0;
}
有人说这不是多此一举吗,直接访问多简单,干嘛还有指针来间接的访问变量,那么就看下面这个应用
#include <stdio.h>
//下面有2个交换函数
void swap1(int a,int b)
{
int t;
t = a;
a = b;
b = t;
}
void swap2(int *p1,int *p2)
{
int t;
t = *p1;
*p1 = *p2;
*p2 = t;
}
int main(void)
{
int a = 10,b = 20;
swap1(a,b);
printf("%d %d\n",a,b); //a还是10,b还是20
swap2(&a,&b);
printf("%d %d",a,b); //a变成了20,b变成了10
/*
* swap1并不能对主函数中的a,b值进行交换,原因是形参的地址和实参的地址是不同的
* swap2他把a,b的地址给了形参
*/
return 0;
}
2. 指针与数组
指针可以指向数组的首地址来访问数组的所有元素
#include <stdio.h>
int main(void)
{
int a[3] = {0,1,2},i;
int *p = a; //或者p = &a[0],都是表示数组的首地址
//有三种不同的方法用指针访问数组元素
//第一种,最简单的,有点像数组访问
for(i = 0;i < 3;++ i)
printf("%3d",p[i]);
printf("\n");
//第二种,这里的对指针的加i是对p的地址加了i*(int占的内存大小),让其访问第二个地址
for(i = 0;i < 3;++ i)
printf("%3d",*(p + i));
printf("\n");
//第三种,和第二种大体相同,但也有区别,每次++操作后,p的地址会变为下一个元素的开始地址,而不再是原来的地址
for(i = 0;i < 3;++ i)
printf("%3d",*p++);
return 0;
}
下面介绍下2个有趣的声明:
#include <stdio.h>
int main(void)
{
int i;
int (*p1)[3]; //先解读()中的,p1是一个指针,在解读()外面的,这个指针指向大小为3的数组
//所以可以这么用
int a[3] = {0,1,2};
p1 = a;
for(i = 0;i < 3;++ i)
printf("%3d",(*p1)[i]); //输出0,1,2
int b = 10,c = 20,d = 30;
int* p2[3] = {&b,&c,&d}; //[]的优先级大于*,所以p2是一个大小为3的数组,数组中的元素是int*
for(i = 0;i < 3;++ i)
printf("%3d",*p2[i]); //输出10,20,30
return 0;
}
下面我们来说说动态数组,C/C++不像Java可以直接使用变量作为数组的大小,那么如果我们想在程序运行阶段给定数组大小怎么办,那么指针可以完成这个任务
#include <stdio.h>
#include <malloc.h>
int main(void)
{
int *p,i; //我们使用一重指针创建大小一个大小为5的一维数组
p = (int*) malloc(sizeof(int) * 5); //C使用malloc来分配内存空间,C++使用new
for(i = 0;i < 5; ++i)
p[i] = i*i; //使用这些分配的内存
for(i = 0;i < 5; ++i)
printf("%3d",*(p + i));
free(p); //记得释法手动分配的内存
return 0;
}
3. 指针与const修饰符
const可以放在指针的前面也可以放在指针的后面,就来说说他们的区别:
int a = 10,b = 20;
const int * p1 = &a; //p1是一个指针,指向一个被const修饰的int区域
int* const p2 = &a; //p2是一个被const修饰的指针,指向一个int区域
*p1 = 30; //错误
*p2 = 30; //正确
p1 = &b; //正确
p2 = &b; //错误
4. 函数指针
函数指针的用途比较广泛,能在C中的结构体模拟C++的类,扩展函数功能(C++STL中sort函数)
#include <stdio.h>
void exec(void (*p)())
{
(*p)(5);
}
void fun(int i)
{
printf("%3d",i);
}
int main(void)
{
void (*p)(int i);
p = fun; //函数名就是函数的首地址
exec(p); //输出5
return 0;
}