C:数组笔试题


题目一:

请输入以下程序的结果

#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)); //2 5
	return 0;
}

解析:

  • &a 表示取得数组a存储区域的首地址(类型是 int[5] *)
  • *(a +1) == a[1]
  • 则 &a+1 得到的是数组a存储区域的后的地址
  • ptr指针指向数组的最后一个元素后面的那个存储单元的地址,而ptr减1后,再进行数据访问,则访问的是ptr指针的前一个存储单元(a[4])的值
题目二:
#include <stdio.h>

int main()
{
	int a = 6;
	int *p = &a;
	
	printf("%p\n", p);		//0098F97C
	printf("%p\n", p + 0x1);//0098F980
	printf("%p\n", (unsigned long)p + 0x1);//0098F97D
	printf("%p\n", (unsigned int*)p + 0x1);//0098F980
	
	return 0;
}

解析:

  • 指针指向的基类型不一样,虽然加的单元数是一样的,但字节数是不一样的( 0x1 == 1)
  • p 是一个指针类型(int *),所以 p 与 p + 1 相差4个字节

32位处理器可以一次性处理4个字节的数据量,所以是4个字节;
64位处理器可以一次性处理8个字节的数据量,所以是8个字节。

  • (unsigned long)p 将 p 强转为无符号整型,所以 p 与 p + 1 相差 1
  • (unsigned int*)p 基类型还是一个指针类型,所以 p 与 p + 1 相差4个字节
题目三:
#include <stdio.h>

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); //4 2000000 = 0x02000000
	return 0;
}

解析:

  • ptr1[-1] 参考题目1

大端:把高位存储到低地址里面,把低位存储到高地址里面
小端:把低位存储到低地址里面,把高位存储到高地址里面

计算机小端模式存储数组a的数据:
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00

  • (int)a + 1;指向了整个数组内存块的第二个地址,即指向a[0]第二个字节处的地址( 00 00 00 02 ),再以16进制输出( 00 00 00 02 )即 2000000
题目四:
#include <stdio.h>

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

解析:

  • 请参考运算符(逗号表达式)
  • int a[3][2] = { 1, 3, 5, 0, 0, 0 };
题目五:
#include <stdio.h>

int main() {
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%d\n", &p[4][2] - &a[4][2]);//-4

	return 0;
}

解析:

  • p[4][2]偏离首元素位置为18
  • a[4][2]偏离首元素位置为22
题目六:
#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));//10 5
	return 0;
}

解析:

  • &aa 取到的是整个数组的地址
  • &aa + 1 得到的是数组a存储区域的后的地址
  • *(aa +1) == aa[1][0]
题目七:
#include <stdio.h>

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

解析:

  • pa++ == * *(pa + 1)
题目八:
#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);		//POINT
	printf("%s\n", *--*++cpp + 3);	//ER
	printf("%s\n", *cpp[-2] + 3);	//ST
	printf("%s\n", cpp[-1][-1] + 1);//EW 
	return 0;
}

解析:

在这里插入图片描述

  • *cpp[-2] == *(cpp - 2)
  • cpp[-1][-1] == * ( *(cpp - 1)- 1)

在这里插入图片描述

题目九:
#include <stdio.h>

int main()
{
	char *str[] = { "welcome", "to", "Fortemedia", "Nanjing" };
	char**p = str + 1;
	str[0] = (*p++) + 2;
	str[1] = *(p + 1);
	str[2] = p[1] + 3;
	str[3] = p[0] + (str[2] - str[1]);
	printf("%s\n", str[0]);//to后的'\0'
	printf("%s\n", str[1]);//Nanjing
	printf("%s\n", str[2]);//jing
	printf("%s\n", str[3]);//g
	
	return 0;
}

解析:
在这里插入图片描述
在这里插入图片描述

题目十:

数组a的定义语句为“float a[3][4];”,下列()是对数组元素不正确的引用方法。
A. a[i][j]
B. * (a[i]+j)
C. * ( * (a+i)+j)
D. * (a+I*4+j)

正确答案:

D

答案解析:

*(a+i*4+j)

中的a是个数组指针,应该这样写

*(*a+i*4+j)
题目十一:

二维数组X按行顺序存储,其中每个元素占1个存储单元。若X[4][4]的存储地址为Oxf8b82140,X[9][9]的存储地址为Oxf8b8221c,则X[7][7]的存储地址为()。
A. Oxf8b821c4
B. Oxf8b821a6
C. Oxf8b82198
D. Oxf8b821c0

正确答案: A

答案解析:

我们先来看以下的数组:

在这里插入图片描述

从上图直观的看出 X[9][9] 与 X[4][4] 相差 5n - 5 个元素,则有以下计算公式:

[9][9] - [4][4] = 21c-140=5n+5 (1)

[7][7] - [4][4]=x- 140 =3n+3 (2)

[7][7] = 140+3/5*( 21c-140 )= 1c4 (3)

说明:

  • (1)中相减为 DC 为16进制,转换为十进制为 220 算出 n 为 43
  • (2)中计算得出 x 为 1c4 ,切记16进制与十进制的转换。

如有错误,欢迎留言指点!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值