指针运算笔试题解析
- 题目一
- 解析
- 题目二
- 解析
- 题目三
- 解析
- 题目四
- 解析
- 题目五
- 解析
题目一
#include<stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
int *p=(int*)(&a+1);
printf("%d %d",*(a+1),*(p-1));
return 0;
}
答案:2 5
解析
int a[5]={1,2,3,4,5};
先定义一个arr[5]整型数组,将1,2,3,4,5
放置arr[5]中。
int *p=(int*)(&a+1);
取arr数组的地址再加1,使得p指向arr整个数组之后的第一个地址,再强制类型转化为int*类型,使得p的指向就是arr[4]即5
之后的第一个地址。
printf("%d %d",*(a+1),*(p-1));
*(a+1)
指的是arr首元素地址+1,相当于arr[1],所以*(a+1) == 2
;
*(p-1)
指的是5
之后的第一个地址-1,相当于又变为了5
,所以*(p-1) = 5
;
题目二
//x86环境下,结构体的大小为20
#include<stdio.h>
struct Test
{
int num;
char* pch;
short data;
char cha[2];
short arr[4];
}*p=(struct Test*)0x100000;
int main()
{
printf("0x%x\n",p+0x1);
printf("0x%x\n",(unsigned long)p+0x1);
printf("0x%x\n",(unsigned int*)p+0x1);
return 0;
}
答案:
0x100014
0x100001
0x100004
解析
printf("0x%x\n",p+0x1);
这里的p
是struct Test*
类型指向的是struct Test
类型,所以p+1的时候就跳过了一整个结构体,所以p的地址要加20,而地址的存储是以16进制打印的,所以答案就是0x100014
printf("0x%x\n",(unsigned long)p+0x1);
这里的p
被强制类型转化为了unsigned long
,所以p
就变成了一个长整型的整数,故(unsigned long)p+1就是0x100001
printf("0x%x\n",(unsigned int*)p+0x1);
同理,p
被强制类型转化为了unsigned int*
他指向的是unsigned int
类型,p+1的时候就跳过了一整个结构体,所以p的地址要加4,所以答案就是0x100004
题目三
//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);
return 0;
}
答案:4 2000000
解析
int a[4]={1,2,3,4};
先定义一个arr[5]整型数组,将1,2,3,4
放置arr[4]中。
int* ptr1=(int*)(&a+1);
与第一题考法一样,取arr数组的地址再加1,使得p指向arr整个数组之后的第一个地址,再强制类型转化为int*类型,使得p的指向就是arr[3]即4
之后的第一个地址。
int* ptr2=(int*)((int)a+1);
这个比较复杂,需要根据编译器中内存存储的大小端来判断
(大小端不理解可参考数据在内存中的存储)
在这里以VS2022的x86环境为例。
我们先假设数组a的地址为0x00EFF904
,a先被(int)
强制类型转换为了整型,此时a+1
就是地址的整型数字加一,之后a+1
又被(int*)
强制类型转换为了指针类型,所以ptr2
所指向的地址就是0x00EFF905
,我们再回到编译器中,如图:
小端编译器中1
的储存为01 00 00 00
,翻译过来就是00 00 00 01
所以,我们可以推出存储为00 00 00 02
的*ptr2
,所以*ptr2 == 02 00 00 00
,注意:这里的*ptr2
是以16进制所表示的。
printf("%x %x",ptr1[-1],*ptr2);
综上,ptr1[-1] == arr[3] == 4,*ptr2 == 2000000
题目四
#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
解析
这里考察的是逗号表达式,逗号表达式指的是在一个括号中,从左到右以最右的值为返回值
例如:(0,1)
在数组中只表示1
,所以这里的arr
就表示为{ {1,3},{5,0},{0,0} }
,而p
指向arr[0] == {1,3}
的地址,所以p[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;
}
答案:FFFFFFFC -4
解析
由int(*p)[4];
我们可以知道p
是一个指针指向4个整型元素,又因为int a[5][5];
所以我们可以推出下图,而指针与指针的相减就是两指针之间的元素个数,所以我们可以得到:&p[4][2] - &a[4][2] == -4
不过需要注意的是用%p
表示-4
的时候要转化为相应的16进制表达式,推到过程如下:
-4
原码:10000000 00000000 00000000 00000100
反码:11111111 11111111 11111111 11111011
补码:11111111 11111111 11111111 11111100
16进制:FF FF FF FC
所以答案为FFFFFFFC -4
以上就是本期的全部内容了,喜欢请多多关照吧!!!