C语言指针强化(笔记)

文章详细解析了C语言中指针对数组的操作,包括指针的加减、强制类型转换以及对多维数组和字符数组的处理。讨论了指针如何指向数组的元素,如何通过指针访问数组的特定位置,并涉及到逗号表达式和指针数组的复杂用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

int a[5] = { 1,2,3,4,5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d\r\n", *(a + 1), *(ptr - 1));

解析:&a是数组的地址,加1是跳过这个数组,第二个数组的地址,数组的地址不能放在整形指针里面,所以强制类型转换(int*)。整形指针-1是向前挪动一个整形到5的位置,解引用就是5。

int arr6[4] = { 1,2,3,4 };
int* ptr1 = (int *)(&arr6 + 1);
int *ptr22 = ((int*)arr6 + 1);
printf("%d\n", ptr1[-1]);
printf("%d", *ptr22);

解析:

  1. &arr6取出数组的地址,加1是下一个数组的地址,强制转换为int*类型,所以ptr1指针里面arr6这个数组后面的地址。所以ptr1[-1]就是前一个数组最后一个元素4。
  2. arr6的地址(也是首元素地址)转换成整型指针类型,然后加1再转换成地址,就是地址加一个整型大小。所以ptr22解引用就是这个数组的第二个元素2。
int a3[3][2] = { (0,1) ,(2,3) , (4,5) };
int* p;
p = a3[0];
printf("%d", p[0]);

解析:注意里面是(0,1)逗号表达式,存储的是1,最后存储的是1,3;5,0;0,0。指针p指向a3[0]。第0行存储的是1,3,所以最后打印1。

int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);

解析:p=a时会有警告。a[4][2]==(* (* (a+4)+2); a每次加1挪动5个元素,而p加1每次挪动4的元素,所以p加4指向17,解引用再加2指向19个元素,而a指向23的元素。两者相减得-4,

以地址形式打印时:

-4存储为10000000,00000000,00000000,00000000,00000000,00000000,00000000,00000100

取反码:11111111,11111111,11111111,11111111,11111111,11111111,11111111,11111011

加1: 11111111,11111111,11111111,11111111,11111111,11111111,11111111,11111100

打印得FFFFFFFFFFFFFFFC

int arr[2][5] = { 1,2,3,4,5,6,7,8,9,10 };
int *ptr1 = (int *)(&arr + 1);
int* ptr2 = (int*)(*(arr + 1));
printf("%d\r\n", *(ptr1 - 1));
printf("%d\r\n", *(ptr2 - 1));

解析:

  1. &arr取出数组的地址,加1是下一个数组的地址。所以ptr1指针指向arr数组后面的地址。下一个数组向前移动1,就是这个数组最后一个元素10。
  2. arr是首元素地址,就是第一行地址,然后加1是第二行地址,解引用就是第二行数组,再转换成地址。第二行数组向前移动1,就是第一行最后一个元素5。
char\* a\[] = { "work","at","alibaba" };
char\*\* pa = a;
pa++;
printf("%s\n", \*pa);

解析:此时a指向得首元素地址,和二维数组类似,一个元素是一行。然后把指针数组首元素地址赋给了pa。char**pa == char* *pa; *pa的类型是char*,++跳过一个char*数组。pa指向指针数组中得第一个指针元素,++指向第二个指针元素。所以打印at。

char* c[] = { "ENTER","NEW","POINT","FIRST" };
char** cp[] = { c + 3,c + 2,c + 1,c };
char*** cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);

在这里插入图片描述

解析:

  1. cpp指向cp[0],加加(先加加再解引用)后指向cp[1],然后解引用打印POINT。
  2. ++cpp此时指向cp[2],解引用是c[1]的地址,此时再–,是在原来存储顺序上–,而不是在cp里面的顺序,此时指向ENTER。解引用是E的地址,+3是后面E的地址,打印字符串是ER
  3. cpp[-2]=*(cpp-2)是cpp向前移动两个指向"FIRST"的地址。解引用+3指向S,打印字符串ST
  4. cpp[-1][-1] == *(cpp - 1)[-1] == *(*(cpp - 1) - 1)。cpp-1指向cp[1],解引用得到c[2],此时再-1是在原来c顺序上-1,指向"NEW"的地址,解引用得到N地址,再+1得到E地址,打印字符串的EW
  5. 注意:cpp[-2]==*(cpp-2); *cpp[-2]==*(*(cpp-2)); cpp[-1][-1]==*(cpp-1)[-1]==*(*(cpp-1)-1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值