目录
题目一
#include <stdio.h>
int main() {
int a[3][2] = { (0,1), (2,3), (4,5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
结果为1
在代码 int a[3][2] = { (0,1), (2,3), (4,5) };中,(0,1)(2,3)(4,5),都为逗号表达式,所以int a[3][2] = { 1, 3, 5 }; a[0] 表示二维数组的第一行元素的数组名,数组名表示一维数组的首元素地址 即&a[0][0] , p[0] 为 *(p + 0),即 *(&a[0][0]) = 1
题目二
#include <stdio.h>
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;
}
结果为FFFFFFFC,-4
p的类型为 int(*)[4] 是一个指向存放4个元素数组的指针,在代码 p = a 中,a表示二维数组的首地址,即第一行元素一维数组的地址&a[0],,它的类型是int(*)[5],是存放5个元素的指针,注意&a[0]的地址也是从一维数组a[0]中的第一个元素的地址开始。
由上图可得知&p[4][2]的位置,以及&a[4][2]的位置。
%p 是打印地址(16进制表示),%d是打印有符号的整数
&p[4][2] - &a[4][2] 用%d打印出的值为-4,表示它们之间相差4个元素个数,在32位操作环境下用%p打印出的结果为FFFFFFFC(由-4的补码再转为16进制得来)
题目三
#include <stdio.h>
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;
}
结果为:10,5
二维数组aa[2][5] 如上图所示
(int*)(&aa+1):
&aa表示整个二维数组的地址,加1表示跳过一个int(*)[2]的空间,即跳过这一整个二维数组的空间大小。(int*)表示把(&aa+1)的int(*)[2]类型强制转换。
(int*)(*(aa+1)):
aa是二维数组的数组名,表示二维数组的首元素的地址,即&aa[0],它的类型是int(*)[5],加1表示跳过这个类型大小空间,即为&aa[1],*(&aa[1])为aa[1],是一维数组的数组名,表示它首元素的地址&a[1][0],它的首元素的地址类型为(int*),前面的(int*)是一个干扰的行为。
在代码*(ptr1 - 1)中,ptr1 为int(*)类型的,减1表示往前位移一个int类型大小的空间,位移后为10的地址,再解引用为10
在代码*(ptr2 - 1)中,ptr2也为int(*)类型的,减1表示往前位移一个int类型大小的空间,位移后为5的地址,再解引用为5
题目四
#include <stdio.h>
int main() {
char* a[] = { "work", "at", "alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
结果为at
char* a[ ] 是一个字符型的指针数组,存放的元素的类型为char*。存放的是每个字符串首元素的地址。
pa是一个二级指针变量,存放了指针数组a的地址。pa++表示 a++,即 a+1,是数组第二个元素的首地址。故用%s打印后为字符串at
题目五
#include <stdio.h>
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;
}
结果:
POINT
ER
ST
EW
1、**++cpp:先运算cpp++,等于cp++即cp+1,*(cp+1)为 c+2 ,*(c+2)为字符串POINT的首地址,打印即为POINT
2、*--*++cpp + 3:
此时的cpp存放的是cp+1。先运算cpp++,变为cp +2,此时为cp数组中的第三个元素的地址,再运算它左边的解引用符,*(cp+2)为c+1 ,c+1为数组c中第二个元素的地址,再运算--,--(c+1)为 c+0 的地址,再解引用*(c)为字符串ENTER的中元素的首地址,最后再运算加号,加3为字符串中字符E的地址,最后打印出ER。
3、 *cpp[-2] + 3:
此时的cpp指向的位置如上图所示
*cpp[-2] + 3 可写为 *( *(cpp-2) ) + 3,cpp - 2 为 cp的首地址,解引用后为c+3,*(c+3) 为字符串FIRST的首元素地址,最后加3是字符S的地址,最后打印出ST
4、cpp[-1][-1] + 1:
此时的cpp存放的依然是cp+2的地址, cpp[-1][-1] + 1 可写为 *( *(cpp - 1) - 1 ) + 1,cpp - 1即为cp+1,*(cp+1)为 c+2 ,*(c + 2 - 1) 为*(c + 1) ,即为字符串NEW的首元素地址,最后再加1,为字符串NEW中字符E的地址,最后打印为EW
创作不易,觉得还不错请点个免费的赞哦