指针笔试题(帮助你全面理解指针)

目录

笔试题1:

笔试题2:

笔试题3:

笔试题4:

笔试题5:

笔试题6:

笔试题7:


 

笔试题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;
}

程序的结果是什么呢?

首先我们来运行一下程序:

e2c71220d4f74b1681d40a9b113adb20.png

则答案为    2     5

详细分析:

cccc74457a7644b2be7cb7e5e125f4f5.png

&a-------int(*)[5](类型),如果要将&a赋值给p,则有int (*p)[5] = &a

&a是数组的地址,&a+1跳过整个数组

&a+1强制类型转换为和指针变量ptr相同的类型,ptr-1表示减去一个整型的地址

*(a+1)a是数组名,表示首元素地址,a的类型为(int*),如图a位置,加1表示跳过一个元素,指向2的位置,如图a+1,解引用后值为2。

笔试题2:

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
	p = (struct Test*)0x100000;
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

程序的结果是什么呢?

运行代码:

edb0a94f9cc44631b26ce2ba13475fc7.png

 则答案为    00100014    00100001    00100004

详细分析:

p+0x1:表示p+1,指针加1(取决于指针类型——结构体指针),此结构体类型的大小为20个字节,所以增加20,而地址的表示方法是16进制,20的16进制为14,最终结果为00100014。

(unsigned long)p+0x1:p是一个结构体指针类型,将结构体指针类型强制类型转换为unsigned long类型,整形加1就是加1,结果为00100001。

(unsigned int*)p+0x1:将结构体指针类型强制类型转换为unsigned int*类型,整形指针+1,跳过4个字节,最终结果为00100014。

笔试题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;
}

程序的结果是什么呢?

运行代码:

cc62150644c54948bd4870a92957400c.png

则答案为    4    2000000

详细分析:

b0e529900320418c99286e0b6ea5d485.png

%p --------- 是打印地址

%x --------- 是16进制的格式打印

&a+1:增加一个数组a的大小;将其转化为int*类型在赋给指针变量ptr1。如图所示

(int)a + 1:a是一个数组名,表示首元素地址,首元素的地址强制类型转换为整形,整形加一就是加一,跳过一个字节;将其转化为int*类型在赋给指针变量ptr2。

ptr1[-1] ------->  *(ptr1-1)

ptr1为一个整型指针,整形指针减一,即向前移一个整型,如图所示 ptr1-1,解引用向后访问四个字节(04  00  00  00),即为4

ptr2为一个整型指针,解引用向后访问4个字节,如图所示(00  00  00  02),假设是小端放入,还原回来就是(02  00  00  00),16进制打印出来就是0x2000000

笔试题4:

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

程序的结果是什么呢?

运行代码:

d374ca6c3625447694c808a52add3094.png

则答案为    1

详细分析:

5cb86deeabba4b62847e1b0760735140.png

区别于:int a[3][2] = { {0, 1}, {2, 3}, {4, 5} };

原题为逗号隔开的表达式,表达式结果为:int a[3][2] = { 1, 3, 5 };

a[0]:第一行的数组名,没有单独放入sizeof内部,数组名表示首元素地址。相当于&a[0][0]

p[0]  --------->  *(p+0)

笔试题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;
}

程序的结果是什么呢?

运行代码:

2c19ef50b9bd4644aa234ac4658c3b74.png

则答案为    FFFFFFFC   -4

详细分析:

4cc7d41dfcc84b9bbd7ab649e0301208.png

int (*p)[4]:p为一个指针,指向一个数组,是四个元素,每个元素是整形

把a赋值给p,a是一个数组名(表示首元素的地址),即二维数组的第一行地址

a--------->int (*)[5]类型      p------->int (*)[4]类型

p+1:跳过4个整形

p[4][2] ----------->  *(*(p+4)+2):对于p+4(数组指针)解引用有权利会访问到4个整形元素

&p[4][2] - &a[4][2]:指针和指针相减得到的是指针之间的元素个数,小地址减大地址(负数),得到-4,

-4:以%d打印就是 -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;
}

程序的结果是什么呢?

运行代码:

b1a7dad71fe54a4a86b0518f6722c3d7.png

 

则答案为    10    5

详细分析:

40d139672af9489fa745ced28cf6adc3.png

二维数组的本质是一维数组,比如此题的数组aa表示数组内含有两个元素,分别是两个一位数组,

而这两个一维数组又分别包含五个元素。

&aa+1:aa表示整个数组的地址,加1为跳过整个数组。

*(aa+1):aa为数组首元素的地址(第一行的地址),加1(第二行地址),解引用得到第二行(*(aa+1) ---------> aa[1]----第二行的数组名没有单独放入sizeof内部,也没有取地址,表示首元素地址,即&aa[1][0])

 ptr1和ptr2都为指针,指针减整型,减去存储内存的元素的类型。

ptr1-1:向前移动一个整型指针,解引用得到10

ptr2-1:向前移动一个整型指针,解引用得到5

笔试题7:

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

程序的结果是什么呢?

运行代码:

25b73c3e36864fceb23d022a5e9d3b3c.png

则答案为    at

详细分析:

f2920b58470947a9b5bb5313b5896933.png

char* a[]为指针数组,是数组用来存放指针,该数组有三个元素,分别是三个字符串的地址。

pa = a:是将数组a的首元素的地址放入二级指针变量pa中。

pa++:跳过一个char*的元素

*pa:此时pa为a[1],也就是第二个元素表示字符串的首地址,以%s的形式输出,依次打印字符串。

 

 

 

 

  • 10
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗小温

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值