指针和数组笔试题解析

目录

一维数组

字符数组

二维数组

指针笔试题


 数组名的意义:
1. sizeof(数组名),数组名表示整个数组,计算整个数组的大小。
2. &数组名,数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。

一维数组

	int a[] = { 1,2,3,4 };
1.	printf("%d\n", sizeof(a));
2.	printf("%d\n", sizeof(a + 0));
3.	printf("%d\n", sizeof(*a));
4.	printf("%d\n", sizeof(a + 1));
5.	printf("%d\n", sizeof(a[1]));
6.	printf("%d\n", sizeof(&a));
7.	printf("%d\n", sizeof(*&a));
8.	printf("%d\n", sizeof(&a + 1));
9.	printf("%d\n", sizeof(&a[0]));
10.	printf("%d\n", sizeof(&a[0] + 1));

1.sizeof(数组名)表示整个数组的大小,答案为4*sizeof(int)=16

2.a没有单独放在括号中,则a表示首元素地址,地址大小为4/8(32位平台下地址4字节,64位平台下地址8字节)

3.a表示首元素地址,*a表示首元素,首元素为int类型,大小为4

4.同问题二,大小为4/8,a+1表示下标为2的地址

5.a[1]表示下标为1的元素,大小为4

6.&a表示整个数组的地址,地址大小为4/8

7.&a表示整个数组的地址,类型为int (* )[4],如果解引用,则访问4个int的数组,大小为16

8.&a+1表示地址,大小为4/8

9.&a[0]表示首元素地址,大小为4/8

10.&a[0]+1表示第二个元素的地址,大小为4/8

字符数组

	char arr[] = { 'a','b','c','d','e','f' };
1.	printf("%d\n", sizeof(arr));
2.	printf("%d\n", sizeof(arr + 0));
3.	printf("%d\n", sizeof(*arr));
4.	printf("%d\n", sizeof(arr[1]));
5.	printf("%d\n", sizeof(&arr));
6.	printf("%d\n", sizeof(&arr + 1));
7.	printf("%d\n", sizeof(&arr[0] + 1));

1.sizeof(数组名)表示整个数组的大小,答案为6*sizeof(char)=6

2.arr表示首元素地址,地址大小为4/8

3.*arr表示首元素,首元素为char类型,大小为1

4.arr[1]表示第二个元素,大小为1

5.&arr表示整个数组的地址,大小为4/8

6.&arr+1表示地址,大小为4/8

7.&arr[0]表示首元素地址,+1表示第二个元素的地址,大小为4/8

8.	printf("%d\n", strlen(arr));
9.	printf("%d\n", strlen(arr + 0));
10.	printf("%d\n", strlen(*arr));
11.	printf("%d\n", strlen(arr[1]));
12.	printf("%d\n", strlen(&arr));
13.	printf("%d\n", strlen(&arr + 1));
14.	printf("%d\n", strlen(&arr[0] + 1));

8.arr表示首元素地址,但数组中没有'\0',strlen计算停止位置未知,结果是随机值

9.同8

10.*arr表示首元素,不是地址,程序无法运行

11.arr[1]表示第二个元素,程序无法运行

12.&arr表示整个数组的地址,类型为char (* ) [6],但strlen参数类型为char*,传入参数后按char*类型计算,结果仍是随机值

13.&arr+1表示整个数组之外的地址,仍是随机值

14.&arr[0]+1表示第二个元素的地址,结果仍是随机值

总结:

sizeof用来计算占用内存空间的大小

strlen用来计算字符串中\0为止,之前出现的字符的个数

	char arr[] = "abcdef";
1.	printf("%d\n", sizeof(arr));
2.	printf("%d\n", sizeof(arr + 0));
3.	printf("%d\n", sizeof(*arr));
4.	printf("%d\n", sizeof(arr[1]));
5.	printf("%d\n", sizeof(&arr));
6.	printf("%d\n", sizeof(&arr + 1));
7.	printf("%d\n", sizeof(&arr[0] + 1));

"abcdef"末尾有'\0',相当于char arr[] = { 'a','b','c','d','e','f','\0'};

1.sizeof(数组名)表示整个数组的大小,答案为7*sizeof(char)=7

2.arr+0表示首元素地址,大小为4/8

3.*arr表示首元素,首元素为char类型,大小为1

4.arr[1]表示第二个元素,大小为1

5.&arr表示整个数组的地址,大小为4/8

6.&arr+1仍然表示地址,大小为4/8

7.&arr[0]+1表示第二个元素的地址,大小为4/8

8.	printf("%d\n", strlen(arr));
9.	printf("%d\n", strlen(arr + 0));
10.	printf("%d\n", strlen(*arr));
11.	printf("%d\n", strlen(arr[1]));
12.	printf("%d\n", strlen(&arr));
13.	printf("%d\n", strlen(&arr + 1));
14.	printf("%d\n", strlen(&arr[0] + 1));

8.arr表示首元素地址,数组中\0前有6个字符,答案为6

9.arr+0表示首元素地址,答案为6

10.*arr表示首元素,不是地址,程序无法运行

11.arr[1]表示第二个元素,程序无法运行

12.&arr表示整个数组的地址,类型为char (* ) [6],但strlen参数类型为char*,传入参数后按char*类型计算,结果为6

13.&arr+1表示整个数组之外的地址,结果为随机值

14.&arr[0]+1表示第二个元素的地址,结果为5

	char* p = "abcdef";
1.	printf("%d\n", sizeof(p));
2.	printf("%d\n", sizeof(p + 1));
3.	printf("%d\n", sizeof(*p));
4.	printf("%d\n", sizeof(p[0]));
5.	printf("%d\n", sizeof(&p));
6.	printf("%d\n", sizeof(&p + 1));
7.	printf("%d\n", sizeof(&p[0] + 1));

1.p为指针变量,大小为4/8

2.p+1表示第二个字符的地址,大小为4/8

3.*p表示一个char类型,大小为1

4.p[0]->*(p+0)->*p,大小为1

5.&p表示指针变量p所在的地址,大小为4/8

6.&p+1表示的仍是地址,大小为4/8

7.&p[0]+1->&*p+1->p+1,大小为4/8

8.	printf("%d\n", strlen(p));
9.	printf("%d\n", strlen(p + 1));
10.	printf("%d\n", strlen(*p));
11.	printf("%d\n", strlen(p[0]));
12.	printf("%d\n", strlen(&p));
13.	printf("%d\n", strlen(&p + 1));
14.	printf("%d\n", strlen(&p[0] + 1));

8.p表示字符a的地址,直到\0前有6个字符,答案为6

9.p+1表示字符b的地址,直到\0前有5个字符,答案为5

10.*p不是地址,无法运行

11.p[0]不是地址,无法运行

12.&p是指针变量p的地址,不是数组中的元素地址,结果为随机值

13.同12,结果为随机值

14.&p[0]+1表示字符b的地址,答案为5

二维数组

	int a[3][4] = { 0 };
1.	printf("%d\n", sizeof(a));
2.	printf("%d\n", sizeof(a[0][0]));
3.	printf("%d\n", sizeof(a[0]));
4.	printf("%d\n", sizeof(a[0] + 1));
5.	printf("%d\n", sizeof(*(a[0] + 1)));
6.	printf("%d\n", sizeof(a + 1));
7.	printf("%d\n", sizeof(*(a + 1)));
8.	printf("%d\n", sizeof(&a[0] + 1));
9.	printf("%d\n", sizeof(*(&a[0] + 1)));
10.	printf("%d\n", sizeof(*a));
11.	printf("%d\n", sizeof(a[3]));

1.sizeof(数组名)表示整个数组的大小,答案为12*sizeof(int)=48

2.a[0][0]表示第一行第一个元素,大小为4

3.a[0]相当于第一行数组的数组名,答案为4*sizeof(int)=16

4.a[0]相当于第一行数组的数组名,数组名相当于首元素地址,a[0]表示第一个元素的地址,+1表示第一行第二个元素的地址,大小为4/8

5.*(a[0] + 1)->a[0][1],表示第一行第二个元素,大小为4

6.a代表第一行数组的地址,+1表示第二行数组的地址,大小为4/8

7.*(a + 1)->a[1]相当于第二行的数组名,答案为4*sizeof(int)=16

8.&a[0]+1->a+1,同6,大小为4/8

9.*(&a[0] + 1)->*(a+1)->a[1],表示第二行数组的数组名,答案为4*sizeof(int)=16

10.*a->a[0],同3,答案为4*sizeof(int)=16

11.a[3]表示第四行数组的数组名,答案为4*sizeof(int)=16

指针笔试题

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+1表示元素5后面的地址,强制类型转换为int*赋给ptr。

*(a+1)表示第二个元素,为2。*(ptr-1)表示元素5。答案为2,5

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

0x开头代表16进制,20即0x14。

p+0x1->p+1,结构体类型指针变量加1跳过一个结构体,即0x100014

将p强制转换为unsigned long类型,加1就是加1,答案为0x100001

将p强制转换为unsigned int*,加1跳过一个整型,即0x100004

结果为0x100014 0x100001 0x100004

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

&a+1表示整个数组后的地址,后转换为int*类型赋给ptr1。

(int)a+1,表示数组首元素地址转换为int类型然后加一,后转换为int*类型赋给ptr2。

ptr1[-1]->*(ptr1-1),表示数组最后一个元素4。

ptr2目前指向数组的第二个字节,根据小端存储,数组在内存中的存储方式为:01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00。解应用访问灰色部分的数据,答案为0x2000000

结果为0x4 0x2000000

int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);
	return 0;
}

注意括号表达式,数组相当于int a[3][2] = { 1, 3, 5 };

a[0]代表数字1的地址,赋给p。p[0]->*p=1

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

&p[4][2]->*(p+4)+2 ,p是数组指针,+1表示跳过4个int,*(p+4)相当于数组名,表示首元素地址,+1跳过1个int,最终&p[4][2]表示a[3][3]的地址,&p[4][2] - &a[4][2],由于是int*类型相减,答案表示两个地址间int变量的个数,又是小地址减大地址,所以答案为-4,以%p形式打印为FFFFFFFC。

最终答案FFFFFFFC,-4

数组a

元素地址

01234
0p/ap+1
1p+2
2p+3
3p+4*(p+4)+2
4&a[4][2]

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+1表示整个数组后面的地址,转换成int*类型赋给ptr1

*(aa+1)表示第二行数组首元素地址,赋给ptr2。

*(ptr1-1)表示最后一个元素10,*(ptr2-1)表示第一行最后一个元素5。

答案为10,5

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

a为指针数组的数组名,数组名代表首元素地址,赋给pa。

pa++,跳过一个char*,指向数组的第二个元素。

对pa解引用找到第二个元素,由于数组的每个元素都是char*类型,所以可以以%s形式打印,

结果为at

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

cpp即cp,++cp指向元素c+2,解引用表示元素c+2,c+2指向元素"POINT"的首字母P的地址,再解引用即表示元素P的地址,为char*类型,以%s形式打印为POINT

由于上一条cpp已经自增一次,这里*++cpp表示元素c+1,--*++cpp表示c,c指向元素"ENTER"的首字母E的地址,解引用表示E的地址,+3指向第4个字母E,结果为ER

*cpp[-2]+3->**(cpp-2)+3,cpp-2回到cp数组的首元素地址,解引用表示首元素c+3,c+3指向元素"FIRST"的首字母F的地址,再解引用表示F的地址,+3指向S,结果为ST

cpp[-1][-1]+1->*(*(cpp-1)-1)+1,cpp-1回到cp数组的第二个元素地址,解引用表示元素c+2,然后-1表示c+1,c+1指向元素"NEW"的首字母N的地址,再解引用表示N的地址,+1则指向E,结果为EW

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

世真

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

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

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

打赏作者

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

抵扣说明:

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

余额充值