C语言指针笔试题

发布时间:2024-11-13 12:01

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

在这里插入图片描述
分析:首先,先看 * (a+1),这是对a的首地址向后移动一个单位,也就是第二个地址,然后再解引用,也就是数组第二个元素,就是2。然后我们再看第二个输出,int * ptr = (int * )(&a + 1),这里是把取的a数组的整个地址,然后加1,就是下一个数组的首地址,然后再看输出 * (ptr - 1),这里ptr减1,就是a的末尾的地址了,再解引用,就是5。

2、
第二个代码和输出。

struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}

C语言指针笔试题_第1张图片
这里首先定义了一个结构体类型的指针p,我们认为结构体的大小是20个字节。
printf("%p\n", p + 0x1);//这里是加上了20个字节,转换成16进制就是0x100014。
printf("%p\n", (unsigned long)p + 0x1);//这里强转成了无符号整形,所以就相当于加1个字节,就是0x100001。
printf("%p\n", (unsigned int*)p + 0x1);//这里强转成了无符号整形指针,相当于加4个字节,就是0x100004。
注意:我们已经说过了,对指针加减整数,就是加减上sizeof(type)乘整数。
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;
}

在这里插入图片描述
首先,解释以下第一个输出,ptr1定义为下一个数组的首地址,再减1,就是a的末尾元素的地址,再解引用,就是4。
然后,我们来画图解释一下第二个输出的意思。
C语言指针笔试题_第2张图片第一个图,我们可以看到a[4]这个数组和ptr所指向的位置。每一个空格代表一个字节。
C语言指针笔试题_第3张图片第二个图,* ptr2是对ptr2解引用,是ptr所指向的对象。因为ptr的类型是int * ,所以解引用后的元素是Int类型,需要向后扩展四个字节,也就是绿色方框括出来的。
C语言指针笔试题_第4张图片
第三个图,数组的存储地址的规律是由低到高,连续递增。第一个元素1就是0x 00 00 00 01,第二个元素2就是0x 00 00 00 02。又由于我们是小端的计算机,这里解释一下小端的概念,就是把权重小的数值放在低地址处,权重大的放在高地址处,权重的大小就是距离0x的远近,离得远的权重小,离得近的权重大。解释完了小端的概念,我们就知道为什么前面四个字节填 01 00 00 00 ,所以最后取得数就是 00 00 00 02 ,又因为是小端,所以输出的是 0x02 00 00 00了。
4、
第四个代码和输出。

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 = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);

那么请问,c最后的值是多少呢?答案是13。
在这里插入图片描述
为什么是13呢?我们看c等于的右半部分,(a > b, a = b + 10, a, b = a + 1),这里就是一个逗号表达式,里面的部分从左到右依次执行,整个程序的结果是最后一个表达式。a>b是0;a=b+10,a=12;a=12;b=a+1,b=13。所以这个表达式最后的结果就是13。

我们再回头看最开始的代码就可以理解了,int a[3][2] ={(0, 1), (2, 3), (4, 5) },这是一个三行两列的二维数组,第一行赋值1,第二行赋值3,第三行赋值5,空缺部分补0。
这里打印的是第一个元素,所以打印1。
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;
}

在这里插入图片描述
这个代码需要画图解释。
C语言指针笔试题_第5张图片
上图是int a[5][5]二维数组的示意图。
C语言指针笔试题_第6张图片

这里说一下int( * p) [ 4 ] ,这是一个数组指针,指向数组,每个数组有4个int。p [ 4 ] [ 2 ]可以理解为 * ( * (p+4 ) +2 )。 * (p+4 )定义到绿色圆圈位置, * ( * (p+4 ) +2 )再向后移动两个Int,就到了红色方框的位置。
C语言指针笔试题_第7张图片&a[4][2]就是紫色方框的位置,由原来的知识可知, &p[4][2] - &a[4][2]是两个指针相减,是指针之间经过元素的个数,所以结果就是-4。所以第二个打印的数字应该是-4,第一个打印的数组按照16进制解释,打印出来就是0xFF FF FF FC。
6、
第六个代码和输出。

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

C语言指针笔试题_第8张图片
要解释这个代码,也需要画图。
C语言指针笔试题_第9张图片上图就是前三行代码所表达的意思。c,cp,cpp都是指针数组,但是他们内部存放的指针分别是一级指针、二级指针和三级指针。
第一个打印数:
printf("%s\n", **++cpp);//这里先对cpp++,再连续解引用两次,就打印出"POINT"。
第二个打印数:
printf("%s\n", ++cpp+3);//这里是先对cpp++,解引用,再–,再解引用,然后加3。
这里有个点需要注意,因为进行“++”操作,原数据会产生变化。所以当第一个打印数打印完之后,后面这个cpp已经指向了cp的第二个元素。所以会打印“ER”。
printf("%s\n", * cpp[-2]+3);// * cpp[-2]可以理解为 * ( * (cpp-2)),cpp-2就会移动到cp的初始位置,然后解引用,是cp的第一个元素,然后再解引用,就是"FIRST",再加3,就打印“ST”。
printf("%s\n", cpp[-1][-1]+1);//cpp[-1][-1]可以理解为 * ( * (cpp-1)-1),cpp-1移动到cp的第二个元素的地址处,然后解引用,是第二个元素。cp第二个元素减1,就移动到cp的第二个元素的地址处,再解引用,就是第二个元素,对应的字符串就是“NEW”,再加1,移动到E处,所以打印“EW”。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号