指针笔试题

笔试题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+1跳到了数组后面第一块地址,将地址给了int* ptr。

*(a+1):a+1 == 首元素地址+1 == 2的地址,*就是2。

*(ptr-1):ptr-1是向后跳过4个字节,它是int类型,ptr-1 == 5的地址,*就是5。

笔试题2:

在x86环境下

struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x00000000。 如下表表达式的值分别为多少?
//已知,结构体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;
}

加16进制的1和加10进制的1是一样的

p + 0x1:p是结构体指针,这个结构体有20个字节,p+1就是跳过20个字节(+20)。

(unsigned long)p + 0x1:无符号长整形+1,就是+1,p强转了不是指针。

(unsigned int*)p + 0x1:无符号整形指针+1,是跳过1个字节(+4)。

%p是十六进制显示的

笔试题3:

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);
return 0;
}

ptr[-1]:  ptr[-1]==*(ptr-1)==4

*ptr2:  ptr2存放的是(int *)((int)a + 1),a是首元素地址转化为int类型+1,地址作为整形+1从内存上看就是跳过1个字节。

笔试题4:

int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
return 0;
}

​

a存放的内容:{1,3,5,

                         0,0,0}

p存放的是a数组第一行的数组名,p[0]==第一行的首元素==1。

笔试题5:

​
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[4][2]==*(*(a+4)+2),a是首行地址每行类型是int[5],+4是跳过了20个元素,*(a+4)的类型是int,+2是跳过2个元素。

p[4][2]==*(*(p+4)+2),p就直接看跳过了几个元素,p的类型是int*[4],p+4跳过16个元素,*(p+4)的类型是int,+2跳过2个元素。

&p[4][2] 与 &a[4][2]之间隔了4个元素,&p[4][2] - &a[4][2]==-4,-4以%p的形式打印的是它的补码FFFFFFFC。

笔试题6:

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;
}

*(ptr1-1):&aa+1是aa数组后面第一块内存地址,ptr-1==10的地址,*(ptr-1)==10.

*(ptr2-1):二维数组也是多个一维数组在内存连续存放,aa+1是第一个一维数组的地址,这些数组是int[5]类型,+1跳过20个字节(5个int类型的元素),*(aa+1)==第二个一维数组的数组名(b的地址)。*(ptr2-1)==5

笔试题7:

int main()
{
char *a[] = {"work","at","bubble"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}

这种题我们可以画图来理解:

a存放的是w的地址,char**pa=a,就是存放的是a首元素的地址

pa++,是存放的首元素地址+1,pa==a+1

这时*pa拿到的就是"at"a的地址

笔试题8:

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=cp后的图:

**++cpp:++cpp==cp+1,*++cpp==c+2,**++cpp=='p'的地址。打印结果是POINT.

*--*++cpp+3:前面++cpp改变了cpp的值,cpp==cp+1。++cpp==cp+2,*++cpp==c+1,

--*++cpp(这里--不会改变cpp的值)==(c+1)-1==c,*--*++cpp=='E'的地址,E是char类型,地址+3就是跳过三个字节,*--*++cpp+3=="ENTER"中"ER"E的地址。打印结果是ER.

*cpp[-2]+3:cpp==cp+2,cpp[-2]==*(cpp-2)==*(cp)==c+3,*cpp[-2]==*(c+3)=='F'的地址,"FIRST"F地址+3就是S的地址,*cpp[-2]+3=='S'的地址。打印结果是ST

cpp[-1][-1]+1:cpp==cp+2,cpp[-1]==*(cp+1)==c+2,cpp[-1][-1]==*(c+1)=='N'的地址,"NEW",cpp[-1][-1]+1=='E'的地址。打印结果是EW

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值