(1)定义
对一个内存单元来说,指针就是内存单元的地址,举例来说,我们在银行存取款时,银行工作人员根据账号查找存单,找到之后在存单上填入存款、取款的金额。在这里,存单内似于存储单元,账号就是存单的地址,存款数即是存单的内容。在c语言中,每种数据类型的数据(变量或数组元素)都占用一段连续的内存单元。该数据的地址或指针就是指该数据对应存储单元的首地址。
(2)指针的大小
x86或者32位平台,指针4字节
x64或者64位平台,指针8字节
//以下运行结果都是在64位平台上执行的
# include <stdio.h>
void Show(int arr[10]) //这个数组已经退化为指针
{
printf("%d\n",sizeof(arr));
}
int main()
{
printf("%d\n",sizeof(char*)); //8
printf("%d\n",sizeof(short*)); //8
printf("%d\n",sizeof(int*)); //8
printf("%d\n",sizeof(long*)); //8
printf("%d\n",sizeof(long long*)); //8
printf("%d\n",sizeof(float*)); //8
printf("%d\n",sizeof(double*)); //8
printf("%d\n",sizeof(double**)); //8
printf("%d\n",sizeof(double*********)); //8
int arr[10] = {1,2};
printf("%d\n",sizeof(arr)); //40
Show(arr); //8,之所以结果是8,是因为函数中的数组已经退化为指针
return 0;
}
由以上结果可以看出,指针大小取决于它所用的平台,和指针类型无关
(3)指针的赋值
赋值:
左值:放在赋值符号左边,使用写权限
右值:使用读权限
注意:指针类型一样才能赋值
例如:
int main()
{
char a;
int *p = &a;
int *p = char * ; //error,指针类型不一样
int a;
char *p1 = &a;
char *p1=int *; //error,指针类型不一样
int a;
int *p = &a;
int **p2 = &a;
int **p2 = int *; //指针类型一样,所以是正确赋值
return 0;}
&:取地址符
注意区分按位与和取地址符:
1.按位与(&):双目运算符 例如:5&6,a&b
2.取地址(&):单目运算符 ,左边没有操作数
指针==地址;
获取任何变量的地址都是:&变量名;
*指针变量名,则间接访问(跳到,解引用)到指针指向的变量。
int main()
{int a = 10;
int b = 20;
int *p = &a; //定义时*说明p是个指针(地址)变量
*p = 100; //a = 100;
p = &b;
*p = 200; //b=200;
int **pp = &p; //int a,&a->int*,int *p,&p->int **
*pp = &a; //p=&a,把a的地址放到p中
**pp = 1000; //*p = 1000;a=1000;
*pp = &b; //p = &b;
**pp = 2000; //*p = 2000;b =2000;
//int *q;
//pp = &q;
//pp = &a; //error
return 0;}
(4)传值
子函数想要修改父函数的值,必须要:1.传指针。2.解引用。
void Swap_err1(int a,int b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
//printf("%d,%d\n",a,b); //只有在函数中写printf语句才能实现正确结果,没有printf语句程序运行出来就是错的结果
}
void Swap_err2(int *p1,int *p2) //有传指针,但是没有解引用
{
int *tmp = p1;
p1 = p2;
p2 = tmp;
}
void Swap_err3(int *p1,int *p2) //有野指针,程序会崩溃
{
int *tmp; //野指针,悬挂指针
*tmp=*p1; //崩溃点
*p1=*p2;
*p2=*tmp;
}
void Swap(int *p1,int *p2) //正确实现方法
{
int tmp=*p1;
*p1 = *p2;
*p2 = tmp;
}