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表示整个数组的地址,+1表示跳过整个数组
它属于数组指针,需要强转成int*类型的指针才能赋给ptr
而ptr属于整型指针,-1跳过四个字节,也就是说(ptr-1)指向对应数字5的位置,解引用之后得到数字5
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;
}
先自己思考一下,然后再看解析哦
【解析】
p是结构体指针,+1跳过20个字节
注意用16进制表示,0x100000+0x000014=0x100014
-------------------------
p转换成unsigned long类型时正常计算0x100000+0x000001=0x100001
-------------------------
int*类型指针+1跳过4个字节,所以计算方式为0x100000+0x000004=0x100004
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr = (int *)((int)a + 1);
printf( "%x", *ptr);
return 0;
}
先自己思考一下,然后再看解析哦
【解析】
a表示首元素地址,转换成int类型再+1,相当于只是跳过一个字节
我们看该数组再内存中的存储方式(小端存储)
低地址 高地址
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
原先首地址读取的内容 0x1
低地址 高地址
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 移动一个字节后
变成0x2000000
所以输出的内容就是0x2000000
#include
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf("%d", p[0]);
return 0;
}
先自己思考一下,然后再看解析哦(此题很坑!)
【解析】
括号仅仅表示的是优先运算,而不是表示数组每行的分隔(花括号才表示二维数组中的分行),所以此数组可以简化为a[3][2]={1,3,5}
p表示的是首元素的地址,即第一行的地址,而p[0]表示的是第一行的第一个元素,即1
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;
}
先自己思考一下,然后再看解析哦
【解析】
a是二维数组,也可以理解为一个数组指针int(*)[5]
p是一个数组指针int(*)[4]
p = a; //表示将a的首元素地址赋给p
a+1跳过5个整型,而p+1跳过4个整型
为了方便理解,我画了个方便理解的图(此类题目非常建议画图)
注:二维数组在内存中也是连续存放的
先看%d打印的,两个地址相减表示的是两者之间的元素个数,而小地址—大地址为负数,据图可得结果为-4
%p是打印地址,而内存中的存储的补码就是地址
即打印结果为-4的补码0xFFFFFFFC
#include
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
先自己思考一下,然后再看解析哦
【解析】
a[]是一个字符指针数组,存放的是三个字符串的首地址信息
而pa是二级指针,指向的是a[]数组的首元素地址,a[0]的地址
pa++表示的是pa指向a[]数组的下一个地址,即a[1]的地址
所以打印*pa即表示打印a[]数组中的第二个元素,即"at"
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;
}
提示:优先级:加号<解引用(间接访问)操作符<自增自减操作符
先自己思考一下,然后再看解析哦
【解析】
根据题目的描述,可以得出初始状态的表示方式:
第一问:
先算自增操作符,所以cpp移到下一位,然后按照连线就可以推出两次解引用后得到的是POINTER
第二问:
先算自增,(注意此处cpp是在第一问的基础上变化的),得在cp+2的位置上,然后自减得c,最后算+3,得ENTER的后两位:ER
第三问(思路与前面类似)
cpp[-2]等价于*(cpp-2),也就是指向cp的位置,存的是c+3的地址,解引用后得FIRST的首地址,最后+3得ST
第四问:
注意此时cpp指向的是cp+2,因为上一问并没有改变cpp的内容,cpp[-1]就是指cp+1的位置,而再算后面的[-1]就是指c+2-1=c+1,最后算+1,所以得NEW的后两位EW