指针面试题目及解析(下)

1.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)则跳过了整个数组,而a为数组首元素地址,因此(a+1)表示数组第二个元素的地址,*(a+1)表示第二个元素2,ptr-1表示跳过一个字节指向5,因此*(ptr-1)表示5,代码运行结果如下:

在这里我们还要理解的问题是,为什么&a+1的类型需要强制转化,这说明&a+1的类型不是int*,

那它是什么类型呢?我们知道,&a为真个数组的地址,如果要使用一个指针接收它,那么我们需要用到数组指针,即int (*P)[5]=&a; 因此&a的类型为int (*)[5],因此为了要达到下面ptr-1跳过一个整形的目的,我们需要强制转换为int*类型。

1.2 题目二

#include<stdio.h>
//在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;
}

 p的类型为struct Test*,且结构体大小为20个字节,即p+0x1跳过20个字节

(unsigned long)p把p强制转换为unsigned long类型,此时p不再是指针了,+0x1只是单纯的加1

(unsigned int)p把p强制转化为unsigned int类型,此时+0x1跳过4个字节

运行结果如下:

 

1.3 题目三

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

a[0]可以理解为第一行的数组名,表示第一行的首元素地址,即p为二维数组第一行首元素地址,所以p[0]表示第一行的首元素,而我们可以看到,在对数组赋值的时候,题目使用的是逗号表达式,相当于int a[3][2]={1,3,5}; 因此p[0]为1,运行结果如下:

 

1.4 题目四

//假设环境是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;
}

 

这道题目,我们可以先画出数组a在内存中的存储状态图,其中a[4][2]的位置我们很容易得到,但是p[4][2]就比较困难了,首先我们看到p的类型为int(*)[4],它是一个数组指针,这表示p指向的数组只有4个元素,现在将数组a的首元素地址赋值给p,则p[0](第一行的首元素地址)指向上图的位置,则p[2],p[3],p[4]依次指向图中的位置,因此得到&p[4][2]指向的位置,我们知道,同类型的地址相减表示两地址间的元素个数,从图中我们看到,这两个地址相差4个元素,且打印的时候为低地址减高地址,故以%d打印的时候为-4,而以%p打印时,是不会区分符号的,而-4的原码二进制表示形式为10000000 00000000 00000100,因此%p会将这个数打印出来,运行结果如下:

 

 

1.5 题目五

#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;
}
//请问输出结果是什么?
	

 &aa为整个数组的地址,&aa+1跳过整个数组,它被强制转化为int*赋值给ptr1

aa为数组首元素地址,即第一行的地址,aa+1跳过第一行指向第二行,为第二行的地址,相当于&aa[1],因此*(aa+1)相当于*&aa[1]==aa[1],即数组第二行的首元素地址

因此*(ptr1-1)=10       *(ptr2-1)=5

运行结果如下:

 

1.6 题目六

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}
//请问输出结果是什么?
	

 a为一个数组指针,表示数组首元素地址,它被赋值于pa,数组a有3个元素每个元素的类型为char*,每个元素指向一个常量字符串的首元素地址,因此pa++指向数组第二个元素,*pa得到数组第二个元素,运行结果如下:

 

 

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值