C语言-指针
一. 指针的概念
指针的用途:高效的访问数据
特征:
高效,简洁(相对于普通变量而言)。
指针可以直接访问物理内存,或者直接操作硬件。(单片机开发)。
内存地址:计算机需要对物理内存进行管理。因为内存空间大,给每个存储单元(1byte)分配一个编号。这个标号就被称为内存地址。
指针:就是指针变量。专门用来存储内存地址的变量。在32位系统中,任意类型的指针大小为4byte (0-0xffffffff)。64位系统中任意类型的指针大小为8byte.(0-0xffffffffffffffff).
指针的类型是多种多样:int*(整形的),char*(字符指针),double*(浮点类型指针)。任意类型的指针大小都是一致。 用指针可以表示任意的数据。
相关的运算符:
&:取地址运算符。获得变量在内存空间中的地址编号。
单目运算符,从右向左结合。
被操作对象,只能是变量。不能是常量,或这表达式。
int a =20;
&a; //获得a变量在内存中的地址。需要输出时应使用%p打印地址。
*:解引用操作符。对地址进行解引用操作。
int main() { int a = 66; char c = 'z'; printf("&a is %p,&a size is %lu\n",&a,sizeof(&a));//整形指针 printf("&c is %p,&c size is %lu\n",&c,sizeof(&c));//字符指针 printf("a = %d\n",*&a);//解引用操作,对象必须是指针 printf("c = %c\n",*&c); return 0; }二. 指针的定义与初始化
int main() { int* pi;//只能指向整形变量的地址 char *pc;//野指针 double *pd = 0;//空指针 float *pf = NULL;//空指针,逻辑上先指向地址为0处的空间,稍后给一个合理的 //地址 int a = 10; pi = &a;//正常初始化 return 0; }注意:1、指针也是有类型的
2、在定义指针时,同时初始化为NULL或者0,防止野指针。
野指针:成因:1、指针未初始化,指向的内存地址随机
2、指针指向的变量内存空间被释放
三. 指针的访问
直接访问变量的内容称为直接访问。
使用指针访问变量的内容称为间接访问。
int main() { int a = 0, b = 0, ret = 0; int *pa = &a, *pb = &b; printf("input two number:"); scanf("%d %d",pa,pb); //使用指针完成加减乘除 ret = *pa + *pb; printf("a + b = %d\n",ret); ret = *pa - *pb; printf("a - b = %d\n",ret); ret = *pa * *pb; printf("a * b = %d\n",ret); ret = *pa / *pb; printf("a / b = %d\n",ret); return 0; }四. 指针的运算操作
int main() { int a = 0, b = 0; int *pa = &a, *pb = &b; printf("&a = %p,&b = %p\n",pa,pb); printf("&a - 1 = %p\n",pa-1); //pb - pa 指向两个不同变量的指针,相减无意义 //pa = pa * 2, pa = pa / 2 指针的相乘相除都无意义 // int arr[10] = { 0 }; int *p1 = &arr[0], *p2 = &arr[9]; int ret = p2 - p1;//在同一数组中,指针减指针得到的是两个指针之间的元 //素个数 printf("p2 - p1 = %d\n",ret); return 0; }对于同一数组来说,指针减指针得到的是两个指针之间的元素个数:
相当于:(p1 - p2) / sizeof(基类型)
4.1 不同类型的指针的解引用操作
指针的类型决定了在使用解引用操作时访问几个字节的大小。比如 int* 类型的指针解引用时可访问4个字节,char* 类型的指针在进行解引用操作时可访问1个字节
如果执行*解引用操作话。假设指针存储的地址是0x2000,则不同类型的指针的解引用有如下操作结果:
char*,取0x2000 开始的1个字节空间的数据
int*,取0x2000 开始的4个字节空间的数据
short*,取0x2000开始的2个字节空间的数据
f1oat*,取0x2000 开始的4个字节空间的数据
double*,取0x2000 开始的8个字节空间的数据
4.2 不同类型的指针的++,--
如果执行++。假设指针存储的地址是0x2000,则不同类型的指针的解引用有如下操作结果:
char*,偏移量 1byte -> 0x2001
int*,偏移量 4byte -> 0x2004
short*,偏移量 2byte -> 0x2002
f1oat*,偏移量 4byte -> 0x2004
double*,偏移量 8byte -> 0x2008
五. 大小端存储方式
大端存储方式:数据的低字节存储在高地址,高字节存储在低地址
小端存储方式:数据的低字节存储在低地址,高字节存储在高地址
大小段存储方式,是由CPU 决定。51单片机,网络设备,都使用大端方式储存数据。
AMD,intel,ARM,都是采取小端存储。
int main() { int a = 1; char *p = (char*)&a;//强制类型转换 if(*p == 1) printf("小端存储\n"); else printf("大端存储\n"); return 0; }