深入理解指针(5)

发布于:2024-04-27 ⋅ 阅读:(26) ⋅ 点赞:(0)

本篇文章主要针对前面学的指针知识进行做题巩固。

下面录用了各个公司的笔试题。

指针运算笔试题解析

题目一:

下面代码输出结果是什么?

#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;
}
  • *(a + 1) = a[1] 所以第一个输出为 2;
  • &a + 1 指向a[5] ~ a[9] 这段区域,返回的是 int(*)[5] 类型,所以赋值给 int* ptr 需要强制类型转换成 int* 类型,存储的地址就是 a + 5 这个地址,所以*(ptr - 1) = a[4] 即第二个输出为 5;

答案:

2,5

题目二:

下面代码输出结果是什么?

//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
#include <stdio.h>
struct Test
{
	int Num;
	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;
}
  • p是一个结构体指针,结构体指针 + 1 对应的地址值 + 结构体的内存大小,所以 p + 0x1 = p的地址值 + sizeof(struct Test)(20),由于16进制打印,所以输出0x00100014;
  • (unsigned long)p 将 结构体指针p 强制转换成 unsigned long 型,所以其进行 + 0x1 操作就是值上进行 + 1 操作,所以输出0x00100001;
  • (unsigned int*)p 将 结构体指针p 强制转换成 unsigned int* 型,所以 p + 0x1 = p的地址值 + sizeof(unsigned int*)(4),所以输出0x00100004。

答案:

00100014
00100001
00100004

题目三:

下面代码输出结果是什么?

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

 注意:二维数组a 中是 ( ) 而不是 { } ,所以 ( ) 中的内容是一个表达式,是一个关于 ' , ' 这个运算符的运算。' , ' 运算返回 ' , ' 最后面的内容的结果。

所以二维数组a其实是 int a[3][2] = {{1, 3}, {5, 0}, {0, 0}};

  • a[0] 可以类比成二维数组首个数组的数组名,所以 int* p = a[0] 等价于 int* p = &a[0][0] 其存储的是二维数组首个数组首个元素的地址。
  • p[0] 可以等价为 *(p + 0) 即 *p

所以输出的结果为 1

答案:

1

题目四:

下面代码输出结果是什么?

//假设环境是x86环境,程序输出的结果是啥?
#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;
}

题目是指针 - 指针,返回的是这两个之间的元素个数。 

  • p 是一个数组指针,指向的数组是4整型元素的,注意a[5][5] 一维数组元素个数为5
  • p = a;   a 可以看成一个int (*)[5] 类型的元素,与p数组指针不是完全一样,p存储 a的第一个一维数组的地址
  • 二维数组虽然我们把其抽象成一个行列的矩阵,但是在内存中还是连续存储,紧挨着一起的。
  • &p[4][2] = &*(*(p + 4) + 2)  意思就是 p的地址值 + 4*( sizeof(int [4]) ) + 2*sizeof( int ) 即 p的地址值 + 18    =     &a[3][3];
  • &a[4][2]    =      &a[3][3] +  4

所以输出结果为FFFFFFFC(-4的补码,由于按照地址形式输出,所以输出-4的补码),-4

答案:

FFFFFFFC,-4

题目五:

下面代码输出结果是什么?

#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;
}
  • &aa表示整个二维数据, &aa + 1*sizeof(aa)跳过了整个二维数组
  • ptr1是整型指针,ptr1存储了10后面的地址,ptr1 - 1 = ptr的值 - sizeof(int),即第一个值输出为10
  • aa 表示首个一维数组,aa + 1 跳过了整个一维数组到 &aa[1]
  • ptr2 是整型指针,ptr1存储了*&aa[1],即aa[1](= &aa[1][0]),ptr2 - 1 = ptr的值 - sizeof(int),即第二个输出为5

答案:

10,5

题目六:

 下面代码输出结果是什么?

#include <stdio.h>
int main()
{
 char *a[] = {"work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0;
}
  • a是一个指针数组,可以拆成 char* a1 = "work" , char* a2 = "at" , char* a3 = "alibaba"
  • pa是一个二级指针。char** pa = a; 意思是 a 是指a这个指针数组的首个元素,就是指针,pa存储这个char*指针
  • pa++,意思是 pa的地址值 + sizeof(char* ),即pa指向"at" 这个指针。所以输出 "at"

答案:

at

题目七:

下面代码的输出结果是什么?

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

 

用这简单的图来表示彼此间的关系。

  •  **++p 由于 *与++是同级遵守从右往左结合所以我们可以看成 *(*(++cpp)) = *(c + 2) = "POINT"
  • *-- * ++cpp + 3 由于 + 优先级最低所以可以解释成  ( * (-- ( *(++cpp) ) ) ) + 3 =  ( * (-- ( c + 1 ) ) ) + 3 = ( * c  ) + 3 =  ( "ENTER" ) + 3 = "ER"
  • *cpp[-2]+3 = *(*(cpp - 2)) + 3 = *(c + 3) + 3 = "ST"
  • cpp[-1][-1] + 1 = *(*(cpp - 1) - 1) + 1 = *( (c + 2) - 1) + 1 = "EW"

答案:

POINT
ER
ST
EW

以上就是本文章的内容了,如果对你有帮助的话,不妨点上免费的赞或关注,感谢支持!