几道指针面试题

	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));  // 2 5

在*(a + 1)中a被隐式转成指向首元素1的指针,加1再解引用得到第二个元素2;&a得到一个int()[5],值为1的地址,加1跳过整个数组,值为5的地址加1,然后强转成int类型。所以*(ptr-1)得到最后一个元素5。

struct Test
{
	int Num;
	char *pcName;
	short sDate;
	char cha[2];
	short sBa[4];
};

struct Test* p = (struct Test*)0x100000; 
	printf("%p\n", p + 0x1); // 00100014
	printf("%p\n", (unsigned long)p + 0x1); // 00100001
	printf("%p\n", (unsigned int*)p + 0x1); //00100004

加1后的值要看变量的类型。指针加1表示其值加上指向的类型在内存中占的字节数。struct Test在内存中占20个字节,所以其指针类型+1在数值上加了20.usigned long类型的p加1在数值上加了1,unsigned int*类型的p加1得到的数值为p+4

int a[4] = { 1, 2, 3, 4 };
	int *ptr1 = (int *)(&a + 1);
	int *ptr2 = (int *)((int)a + 1);
	printf("%x,%x\n", ptr1[-1], *ptr2); // 4,2000000

第一个打印的结果与问题一中类似,&a得到一个数组指针,值为1的地址,加1地址为4后面的地址,强转成int*指向4后面的4个字节。ptr1[-1]就取到4.
(int)a + 1得到的是1的地址加上1.所以再解引用是,*ptr2从元素1的第二个字节开始去四个字节,由于字节序为小端序。所以取到的结果为02000000.

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]);
	//FFFFFFFC,-4

p[4][2]相当于取到数组中第5行第三个元素,即第十九个元素,而a[4][2]取到第23个元素。所以两者之间相差4个元素。所以指针相减得到-4。

int aa[2][5] = { 
		{1, 2, 3, 4, 5},
		{6, 7, 8, 9, 10 } 
	};
	//&aa 应该是一个数组指针 int(*)[2][5], 再 + 1 应该要跳过整个数组
	int *ptr1 = (int *)(&aa + 1);
	// aa 是二维数组名 再 + 1, 隐式转成 int(*)[5]
	int *ptr2 = (int *)(aa[1]);
	printf("%d,%d\n", *(ptr1 - 1), *(ptr2 - 1));// 10,5

这里&aa同前面得到数组指针,类型为int()[2][5],+1跳过了整个二维数组。因此(ptr-1)取到二维数组的最后一个元素10;aa[1]相当于*(aa + 1),aa隐式转成指向首元素的指针,类型为int()[5],+1跳过第一个一维数组,所以(ptr2-1)取到第一个一维数组的最后一个元素5。

char *a[] = { "work","at","alibaba" };
	char**pa = a;
	pa++;
	printf("%s\n", *pa); // at

a是一个指针数组,数组元素的类型为char*,元素有三个,分别存放了三个字符串首字母的地址。pa=a,a隐式转成指向首元素的指针类型,即char**类型,将其值(work中w的地址地址)赋给pa,pa++得到字符串“at”中a的地址,打印得到字符串at。
7.

char *c[] = { "ENTER", "NEW", "POINT", "FIRST" };
	char**cp[] = { c + 3, c + 2, c + 1, c };
	char***cpp = cp;

	printf("%s\n", **++cpp); //POINT
	printf("%s\n", *--*++cpp + 3);//ER

	// cpp[-2] => *(cpp-2) 这个操作没有修改 cpp 的内容. 而上面的 ++ 操作修改 cpp 
	printf("%s\n", *cpp[-2] + 3);//ST
	//printf("%s\n", cpp[-1][-1] + 1);// EW
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值