目录
一.基础
1.
2.
二.中等
1. 坑
2.
3.指针+1到底加什么
三.偏难
1.(小端 x86)
2.通过数组指针进行偏移的时候怎么偏移
3. 大BOSS
(1)**++cpp
(2)*-- * ++cpp + 3
(3)*cpp[-2] + 3
(4)cpp[-1][-1] + 1
一.基础
1.
int main()
{int a[5] = { 1, 2, 3, 4, 5 };int* ptr = (int*)(&a + 1);printf("%d,%d", *(a + 1), *(ptr - 1));return 0;
}
&a 是整个数组的地址,类型:int (*)[5] &a+1 的类型还是 int (*)[5]
存到 int * 类型的指针 ptr 中,要强制类型转换。
答案:2 5
2.
int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int* ptr1 = (int*)(&aa + 1);int* ptr2 = (int*)(*(aa + 1));printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}
&aa 是整个数组的地址
*(aa+1) 等价于 aa[1] 是第二行的数组名,是第二行第一个元素的地址。
答案:5 10
二.中等
1. 坑
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int* p;p = a[0];printf( "%d", p[0]);return 0;
}
坑:二维数组内部分行的时候,要用 { } 。 这里的 ( )是3个逗号表达式。
所以题目等价于:
int main()
{int a[3][2] = { 1, 3, 5 };int* p;p = a[0];printf("%d", p[0]);return 0;
}
a[0] 是第一行的数组名,是第一行首元素的地址。 p[0] 等价于 * (p + 0)
答案:1
2.
int main()
{char* a[] = { "work","at","alibaba" };char** pa = a;pa++;printf("%s\n", *pa);return 0;
}
这里的 char* * pa ,第二个 * 告诉我 pa 是指针 ,指向的是 char* 类型的元素
这里的 a 是数组名,首元素的地址,传给 pa 。pa++ 后, pa 指向 a 第二个空间的地址。
*pa 解引用,a 第二个空间放的是 (char * 类型)'a' 的地址。从这里开始打印,直至 \0
答案:at
3.指针+1到底加什么
指针+1,+的是指针指向对象的大小。
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}
1. p 是结构体指针,+1,+的就是一个结构体大小。+20 之后为 0x00100014
2. p 被强制转换为整型,p 里面的值被强制转换为整数。+1 结果为 0x00100001
3. p 是整型指针,整型指针+1,跳过1个整型。整型4字节。 结果为:0x00100004
三.偏难
1.(小端 x86)
int main()
{int a[4] = { 1, 2, 3, 4 };int* ptr1 = (int*)(&a + 1);int* ptr2 = (int*)((int)a + 1);printf("%x,%x", ptr1[-1], *ptr2);// %x :以16进制打印return 0;
}
ptr1[-1] 是 *(ptr1 - 1)
注意:指针+1,+的是指针指向对象的大小。
a 是数组首元素的地址,假设为 0x0012ff40 被强制转换为 int (不是指针)。+1后为:0x0012ff41
再被转换为 int * 整型指针 ptr2。
但是,一个整型是4个字节,0x0012ff41 之加了一个字节,ptr2 并不指向 2 所在的地址
找到 ptr2 所指向的位置,再向后访问4个字节
答案:4 ,2000000
2.通过数组指针进行偏移的时候怎么偏移
int main()
{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]);return 0;
}
p是指向4个整型的数组指针。对 指针 p+1,跳过4个整型
p 的类型:int (*)[4] a 的类型:int (*)[5]
p[4][2] --- *(*(p+4)+2)
指针-指针,结果是中间元素个数。大-小为正,小-大为负。所以题目中相减结果为 -4
-4 用 %d 打印还是 -4 用 %p 打印:
-4
原码:10000000000000000000000000000100
反码:11111111111111111111111111111011
补码:11111111111111111111111111111100
-4 在内存中以补码形式存放,用 %p 打印时,就认为11111111111111111111111111111100是地址。
地址不存在什么原反补。类似于16进制打印:0x ff ff ff fc
3. 大BOSS
int main()
{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);return 0;
}
(1)**++cpp
cpp 里面存放的是 char** 的地址。++跳过一个 char** 的数据
**++cpp 最终拿到 POINT 里面 P 的地址
结果:POINT
(2)*-- * ++cpp + 3
先 ++cpp ,解引用。-- 给里面的值自减1,修改了这块地址。再解引用。+3 后,指向 E 的地址。
结果:ER
(3)*cpp[-2] + 3
cpp[-2] ---- * (cpp - 2) 整个表达式转换:** (cpp - 2) + 3
结果:ST
(4)cpp[-1][-1] + 1
转换:* (* (cpp - 1) - 1) + 1
* (cpp - 1) - 1 这个表达式拿到的值是 c + 1 。不改变里面的值
结果:EW
本篇的分享就到这里了,感谢观看,如果对你有帮助,别忘了点赞+收藏+关注。
小编会以自己学习过程中遇到的问题为素材,持续为您推送文章。