指针:任何数据载入内存,在内存中都有他们的地址,这就是指针。
指针变量:保存数据的地址,就要用到指针变量。
内存:内存是一个很大的字节数组,每一个字节都有固定的大小,由8个二进制位构成,每一个字节都有固定的编号,编号从
0开始。比如一个256M的内存,就有256*1024*1024=268435456个字节,那么地址范围就从0-268435455。程序的变量,常量,函数等当载入内存时,在内存中就有一个编号,这个编号就是该数据的地址了,指针就是这样形成的。
void main(){
int num=97;
char ch='a';
printf("ch的地址%d\n",&ch);
printf("num的地址%d\n",&num);
system("pause");
}
变量ch和变量num在内存模型中的存储:(假设 char占1个字节,int占4字节)
如果一个类型占用的字节数大于1,则其变量的地址就是地址值最小的那个字节的地址。因此num的地址是 0028FF40。
指针变量p1保存num的地址,就说p1指向了变量num,也可以说p1指向了num所在的内存块。
取地址:用&,特殊情况,数组名是第一个元素所在的地址.
解地址:我们要指针变量干什么?当然是用它来操作(读写)数据,对一个指针解地址,就可以取到该内存块对应的数据。解地址就是在指针前加一个*.
void main(){
int num=97;
int * p1=#
int * p2=p1;
printf("%d",*p2);
system("pause");
}
指针两个重要属性:指针的值和指针的类型
void main(){
int num=97;
int *p1=#
char*p2=(char*)#
printf("%d\n",*p1);
putchar(*p2);
system("pause");
}
上面的num变量,地址值是0028FF40,因此p1的值就是0028FF40,这就是指针的值。
同样,p2的值也是0028FF40。
*p1:从0028FF40开始解析,因为p1是int类型的指针,因此连续向后取4位,并且将这4个字节的二进制数据解析成整数97.
*p2:从0028FF40开始解析,因为p2是char类型的指针,因此向后取1位,并且将这1个字节的二进制数据解析成字符‘a’.
结构体与指针:如果p是一个结构体指针,可以使用p->成员访问结构体里面的成员,p->num相当于(*p).num
函数与指针:有时我们可以使用函数的返回值回传数据,但是当返回值有其他用途(返回函数的执行状态或有多个返回值时),我们又想通过函数改变主函数变量的值,这个时候可以使用指针。
#include<stdio.h>
#include<stdlib.h>
void change(int *p1){
(*p1)++;
}
void main(){
int p1=15;
printf("初值:%d\n",p1);
change(&p1);
printf("通过指针改变变量值:%d\n",p1);
system("pause");
}
有的时候我们传入指针,是为了避免大型数据,有时传入一个结构体变量需要很多字节,实参赋值数据给形参需要很多字节数据,效率很低,这时,传递指针可以提高效率,因为指针类型的大小是确定的:x86指针4字节,x64指针8字节,远远比结构体变量小。