C语言--数组&指针笔试题解析(指针:你看我几分像从前)

尊贵的各位大厂码农你们好,是的,没错,我又来找你们来帮我指正文章了,今天的主题是数组和指针的笔试题专栏,大家给掌掌眼,有问题的话还请帮忙斧正哦!

目录

前言:

一,数组笔试题

一,一维数组

二,字符数组

2.1,直接赋值型的字符数组

2.2,字符串赋值给字符数组

 2.3,字符串赋值给字符指针

三,二维数组

二,指针笔试题 

试题1:

试题2: 

 试题3:

试题4:

试题5: 

 试题6:

 试题7:

试题8(重点理解掌握): 

前言:

首先,在开始笔试题之前,首先得了解一下几个问题:

1,sizeof()的作用是求对象所占空间的大小,单位是字节。

2,数组名的几种不同用法所代表的含义,一般情况下数组名代表的是首元素地址,但有两种例外情况,首先sizeof(数组名),这里的数组名代表整个数组。其次取地址数组名,代表的是整个数组的地址。

一,数组笔试题

一,一维数组

对于倒数第三个题有一点要强调一下,就是它跳过了整个数组,但是数组后面的地址空间是未知的,是不是我们这里再求作所占空间大小就是有问题的,答案是并不是,后面的地址只能说我们没访问权限。但是这块地址空间是一定存在的,所以就是单纯的求这块地址空间的大小。

还有*&a,如果是放在sizeof内部,他其实就是相当于sizeof(a),求整个数组的大小,但是如果是放在外面用的话,就是相当于拿到整个数组,也就是数组名,等价于首元素地址。这里二者处在不同位置,含义是不一样的

二,字符数组

2.1,直接赋值型的字符数组

对于第三个第四个这种情况,因为你拿到的是字符,比如字符a,对应ascii码就是97,那站在strlen(),你把97传给我,我就把它当成一个地址,但是首先97这个地址编号存不存在,用户能否访问都是一个问题,所以可能就会出现非法访问的问题。

2.2,字符串赋值给字符数组

 

到这里可以给sizeof() 与 strlen() 做一个总结:

sizeof()是一个操作符,返回值类型为size_t的无符号类型,他的作用就是计算对象所占内存空间的大小,不在乎内存中放的什么。

strlen()是一个函数,是用来计算字符串长度的,从给定的地址向后访问 ,直至到\0停止。

 2.3,字符串赋值给字符指针

 

三,二维数组

对于二维数组,这里重点需要注意几个点:

1,注意区分二维数组数组名与第一行的数组名,也就是上面的a 与 a[0],前者表示的是二维数组的首元素的地址,是第一行的地址,而后者表示的是第一行的第一个元素的地址。二者数值一样,但是意义不一样。

2,对于sizeof而言,他只是求对象所占内存空间的大小,他的求值依据是对象的类型,而不是真正的会去访问这块内存空间。所以在最后的sizeof(a[3])里面,看似好像越界访问数组了,因为数组只有三行,但是实际上我们并没有真正的访问这块空间,只是说假如有这么一块空间是int [4]类型,然后让你求这块空间所占内存空间的大小。

二,指针笔试题 

试题1:

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

大家觉得结果是什么? 没错,就是2,5,至于为什么是这样,解析如下:

试题2: 

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

首先,定义的p是一个结构体指针,已知他的地址是0x100000。这个题的主要考查点就是不同指针类型,加上整数,移动的步长不同。

解析:

注意%p是让我们用地址的形式打印数据,并不是去找这个地址,所以对于第二个结果而言,他只是用地址的形式打印输出。至于为什么前面会补0,是因为这是在32位系统下,你输出展示得有四个字节,所以前面你得补上两个0,如果打印完全,以第一个为例应该是00000000000000000000000000100014,一共满32位。 

 试题3:

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

 解析:

%x表示以十六进制不带前缀的格式输出结果,所以最后的输出是4,2000000。这里我们小总结一下,%p是以地址形式输出,结果前面会补0,%x是以十六进制不带前缀的格式输出,前面不进行任何补充,如果是%#x,输出结果前面加0x. 

试题4:

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

这个题的结果是什么先不说,只能说这个题有个大坑可能等着你掉进去呢!

仔细看这个数组,长得倒是有模有样的,但是内部不纯,里面放的是逗号表达式,所以结果可不是简简单单的0,那么让我们解析解析:

试题5: 

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

 解析:

 试题6:

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

 解析:

 试题7:

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

 这个题考察的一个点就是将字符串赋值给一个字符数组的时候,本质上不是将一整个字符串存进数组中,存放的只是字符串首元素地址。

试题8(重点理解掌握): 

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

 解析:

 

今天的文章就到这了,如果大家觉得还可以的话,还请帮忙三连三连哦,十分感谢!

 

猜你喜欢

转载自blog.csdn.net/qq_61688804/article/details/123580282