C语言指针典型题(1)
题目一
#include <stdio.h>
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代表的是首元素的地址,(a + 1)是数组第二个元素的地址,所以解引用后就是2。
&a是整个数组的地址,加1后就是跨过一个数组的长度,所以指向的就是元素5的地址的下一个内存单元,减1后就是5的地址,所以解引用后就是5。
答案
2,5
题目二
//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
解析
1.X86平台下地址是4个字节,8为十六进制数,缺少位数需要在前面补0
例如0x100000是00100000
2.指针p变成了结构体类型的指针
3.而后面的加法考察的是指针类型的意义,也就是int类型的指针+1,是加了4个字节,char类型的指针+1是加了1个字节。
4.
所以第一个就是加上20,转换成十六进制数0x14
第二个就是单纯的+1,和地址没有任何关系了
第三个就是加上4,转换成十六进制数0x4
答案
00100014
00100001
00100004
题目三
#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;
}
解析
认真看题,多看两遍,数组里面是逗号表达式
p存放的是a[0]数组的首元素地址,也就是a[0][0]的地址
答案
1
题目四
//假设环境是x86环境,程序输出的结果是啥?
#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;
}
解析
1.p是指针数组,存放了二维数组第一行数组的地址
2.先看第二个%d形式的,指针相减就是元素个数,指向第23的减指向第19的,19,20,21,22,4个。
3.–4转换成8位16进制数。都是对补码进行操作,-4的补码是11111111111111111111111111111100,
所以十六进制数就是FFFFFFF(1111)C(1100)
答案
FFFFFFFC,-4
题目五
#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;
}
解析
注意ptr2等号右面的写法,只有二维数组可以写这么奇怪的形式,因为aa + 1是第二行整个数组的地址,所以可以这样写,如果是一维数组(int*)(*(arr + 1))就是把arr的第二个元素这个数变成十六进制数形式的地址。
答案
10, 5