每日一题-数组与指针

e840be7bb1ac4d4a9e19c4df8cc3dd5a.gif

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

结果:

e4cfd07c65194bb8844084e8a18c29ad.png

分析:

  1. &a是整个数组的地址,&a+1是跳过一个数组,地址+整个数组的字节数,然后将数组指针类型强转为整形指针类型
  2. 此时的a是数组首元素地址,+1就是第二个元素的地址,*(a+1)==arr[1]==2
  3. ptr是一个整形指针,-1后退一个元素,就是arr[4]==5 

 

知识点:数组名的理解,指针的加减运算

2.题目二

[简单]假设在32位环境下,结构体的大小为20字节,打印的是什么?

#include<stdio.h>
struct Test
{
	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;
}

答案:
7e26a337dcaf493580fabfd1fa5618a6.png

分析:

  1. 0x100000一个数,(struct Test*)0x100000强制类型转换为指针变量,就成地址了
  2. p + 0x1,0x1就是1,地址加一加的就是指针所指向类型的大小(字节数),就是0x100000+24=0x100000+0x18=0x100018
  3. (unsigned long)p,将地址转为无符号的8个字节的整形,那么就是加数字1,结果就是0x100001
  4. (unsigned int*)p,将指针变量的类型转换为无符号的整形,那么加1就是加上无符号整形类型的字节数,就是0x100004

知识点:指针加减运算

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

答案:

3896a5acf23e48cebc654ce7249cc8e3.png

分析:

  1. { (0, 1), (2, 3), (4, 5) },这里面为逗号表达式,结果为最后的元素,那么就是{1,3,5},剩余的为0
  2. a[0]是第一行数组名,那就是第一个元素的地址,为整形指针,那么p就是第一个元素的地址
  3. p[0]==*(p+0)==a[0][0]=第一行数组名[0]==1

知识点:二维数组名的理解,逗号表达式的使用

4.题目四

[简单]在32位环境下,程序打印的结果是什么?

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

答案:

e229794bb2154929a704eb2d5c23440b.png

分析:

  1. p是数组指针,该指针指向的数组大小为4
  2. a是数组的地址,存的是首元素的地址,传给p,指针类型会发生改变
  3. &p[4][2]==&*(*(p+4)+2),数组指针p加4就跳过4个数组,解引用就是第5个数组的数组名
  4. 数组名表示首元素的地址,那就是第五个数组的第一个元素的地址,+2跳过两个元素,一共跳过4*4+2=18个元素,那就是第19个元素的地址
  5. &a[4][2]就是第4*5+3==23个元素的地址,因为数组元素的地址是连续的,那么第19个元素的地址-第23个元素的地址就是相差的元素个数,就是-4
  6. -4的原码就是: 1000 0000 0000 0000 0000 0000 0000 0100
  7.             //反码:1111 1111 1111 1111 1111 1111 1111 1011
  8.             //补码:1111 1111 1111 1111 1111 1111 1111 1101
  9. 以地址形式打印就是0xFFFFFFFC,以整形打印就是-4

知识点:二维数组名的理解,不同类型数组指针的访问特性,指针减指针的运算

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

答案:
203e6b6e622046619001c8fcbcd58d9c.png

分析:

  1. &aa是整个数组的地址,加一跳过整个数组,地址就是10后面的那个地址,然后从数组指针转为整形指针
  2. aa就是数组名,就是第一行数组的地址,第一行数组地址加就跳过一行数组,就是第二行数组地址,解引用就是第二行数组名,强转为整形指针,就是6的地址
  3. 那么*(ptr1 - 1)==10, *(ptr2 - 1)==5

知识点:二维数组名的理解,指针加减

6.题目六

[偏难]程序打印的结果是什么?

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

答案:

a75a3dfdd7b64ef395a388f53048a678.png

分析:

  1. a是一个字符指针数组,存的是这几个字符串的首地址
  2. aa是一个二级指针,存的是数组名a的地址,而数组名就是数组首元素的地址,aa就是"work"首字符的地址的地址
  3. 因为地址都是在数组里面的,数组的元素的地址是连续的,pa++就是第二个元素的地址,就是"at"首字符的地址
  4. 以字符串的形式打印,结果就是"at"

知识点:数组元素地址的连续性,二级指针

7.题目七

[重难点]程序打印的结果是什么?

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

分析:

d26cefbb87844b9c952ae1d026898510.png


 

(1).**++cpp

  • 先加加在使用,那就是数组cp第二个元素的地址,解引用一次就是第二个元素,存的是字符串"POINT"的首地址,打印的就是POINT

18eff5c3e7b145f3b6307691d8d4d53c.png

**++cpp


  (2).*-- * ++cpp + 3

 

  1.  *-- * ++cpp + 3,先加加cpp,在上一轮cpp已经自加了,那此时的++cpp就是数组cp中的第三个元素的地址
  2. * ++cpp就是数组cp第三个元素的值,就是c+1,就是指针数组c的第二个元素的地址
  3. -- * ++cpp 就是c+1自身减一,就是指针数组c的第一个元素的地址
  4. *-- * ++cpp就是指针数组c的第一个元素,就是"ENTER"字符串的首字符地址
  5.  *-- * ++cpp + 3就是首字符的地址+3,那就是"ENTER"字符串的字第4个字符的地址,打印的就是"ER"

2f6842ac3aa84d4b906ac98969855dae.png

*-- * ++cpp + 3


 

(3).*cpp[-2] + 3

  1. *cpp[-2] + 3==*(*(cpp-2))+3,经过上两轮cpp已经自加两次了,此时cpp是指针数组cp第三个元素的地址
  2. 那么cpp-2就是指针数组cp第一个元素的地址,*(cpp-2)就是指针数组cp第一个元素
  3. cp的第一个元素的值是c+3,就是指针数组c第4个元素的地址,那么*(*(cpp-2))就是指针数组c中的第四个元素
  4. 指针数组c的第四个元素的值是"FIRST"首字符的地址,+3就是"FIRST"中第四个字符的地址,最后打印的就是"ST"7750ea0962a94848bceabb81102640c4.png

    *cpp[-2] + 3


(4).cpp[-1][-1]+1

  1. cpp[-1][-1]==*(*(cpp-1)-1),cpp-1就是字符数组cp第二个元素的地址,解引用就是cp的第二个元素
  2. cp的第二个元素的值就是c+2,就是指针数组c的第三个元素的地址
  3. *(cpp-1)-1就是指针数组c的第二个元素的地址
  4. 再解引用*(cpp-1)-1就是指针数组c的第二个元素,就是"NEW"首字符的地址
  5. 首字符+1就是"NEW"中的'E'的地址,打印结果就是"EW"

871788fab3064bc18f5aeb2e6fcb94ab.png

cpp[-1][-1]+1


知识点:指针数组,数组名的理解,二级指针,三级指针,指针加减


本章内容结束了,下章见,拜拜!!!

 

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值