【C语言进阶】 指针强化练习(二)

简介: 【C语言进阶】 指针强化练习(二)

题目五

下面这段代码的执行结果是?

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是一个数组指针,指向的数组类型是:int [4]。也就是说p指向一个整型数组,这个数组有四个元素,其次a是二维数组名,表示首元素的地址,二维数组的首元素是a[0],也就是二维数组中第一行那个一维数组,所以a表示首元素地址,就是二维数组中第一行那个一维数组的地址,它的类型是int(*)[5],把这个类型的地址放到类型为int(*)[4]的指针变量里面,是可以强行放进去的。&p[4][2]其中p[4][2]就是&*(*(p+4)+2),这里需要注意p指向的数组只有四个元素,所以p+1跳过四个元素,这里p+4就会跳过16个元素。

3255dcce6d694a06a14cb3b5c5fe3a8e.png

本题最终的结果就是:FFFFFFFC、-4

题目六

下面这段代码的执行结果是?

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跳过整个二维数组,它的类型是int [2][5],然后把这个地址强制转换成int*型;aa数组名表示首元素地址,是第一行一维数组的地址,aa+1表示第二行一维数组的地址,解引用得到第二行的一维数组也就是aa[1],aa[1]是第二行一维数组的数组名,数组名表示首元素地址,也就是aa[1][0]的地址,aa[1][0]就是6,这里也就是6的地址,所以这原本就是一个整形的地址,(*(aa + 1))前面的强制类型转换就可有可无。本题最终的结果就是:10、5

题目七

下面这段代码的执行结果是?

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

本题需要注意的是:首先a是一个字符指针数组,说明a数组里面存放的是字符的地址,而字符串常量的值就是首字符的地址,所以a数组里面存放的就是"work"中'w'的地址、"at"中'a'的地址、"alibaba"中'a'的地址,数组名a表示首元素地址,也就是a[0]的地址,a[0]里面存放的是'w’的地址,所以a[0]的地址就是'w'的地址的地址,也就是指针的地址,所以这用了一个二级指针变量pa来接收。char** pa应该这样来理解:首先* pa中的*告知我们pa是一个指针变量,char*告诉我们这个指针变量指向一个char*类型的数据,所以对pa++,会跳过一个char*类型的数据,此时pa指向a数组中的第二个元素a[1],也就是说此时pa指向'a'的地址,所以对pa解引用就会得到'a'的地址,然后以%s的格式打印,最终在屏幕上打印出:at

2fd373a3852c4737b8bc66e546a1a0e2.png

题目八

下面这段代码的执行结果是?

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

75af91589bc34ea1a6139b5d680177a9.png

**++cpp中++cpp,cpp就指向cp[1], 第一次解引用得到cp[1]这块空间里面的内容,也就是c[2]的地址,第二次解引用得到c[2]这块空间里面的内容,c[2]里面存的是'P'的地址,所以第一次打印出: POINT。*-- * ++cpp + 3,首先++cpp,此时cpp指向cp[2],然后解引用得到cp[2]这块空间里面的内容,也就是c[1]的地址,然后- -,c[1]的地址是一个char*类型的地址。所以- -跳过一个char*类型的数据,此时得到的就是c[0]的地址,解引用得到c[0]这块空间里面的内容,也就是得到'E'的地址,这是一个字符的地址,+3跳过3个字符,此时得到"ENTER"中第二个'E'的地址,所以第二次打印出:ER。*cpp[-2] + 3中的cpp[-2]就表示*(cpp-2),cpp当前指向cp[2],所以cpp-2指向cp[0],*(cpp-2)得到cp[0]这块空间里面的内容,也就是得到了c[3]的地址,所以cpp[-2]表示的就是c[3]的地址,*cpp[-2]得到c[3]这块空间里面的内容,也就是得到了'F'的地址,这是一个char类型(字符)的地址,所以*cpp[-2] + 3会跳过3个字符,此时表示"FIRST"中'S'的地址,最终打印出来:ST。cpp[-1][-1] + 1中的cpp[-1]表示*(cpp-1),cpp当前指向cp[2],所以*(cpp-1)最终得到c[2]的地址,cpp[-1][-1]表示:*(*(cpp-1)-1),其中*(cpp-1)-1得到c[1]的地址,所以*(*(cpp-1)-1)最终得到c[1]这块空间里面的内容,也就是得到'N'的地址,这也就说明cpp[-1][-1] 表示的就是'N'的地址,所以cpp[-1][-1] + 1就表示:"NEW"中'E'的地址,最终打印出:EW


目录
相关文章
|
1天前
|
C语言
c语言指针总结
c语言指针总结
7 1
|
1天前
|
搜索推荐 C语言
详解指针进阶2
详解指针进阶2
|
7天前
|
存储 程序员 C语言
【C 言专栏】C 语言指针的深度解析
【4月更文挑战第30天】C 语言中的指针是程序设计的关键,它如同一把钥匙,提供直接内存操作的途径。指针是存储其他变量地址的变量,通过声明如`int *ptr`来使用。它们在动态内存分配、函数参数传递及数组操作中发挥重要作用。然而,误用指针可能导致错误,如空指针引用和内存泄漏。理解指针的运算、与数组和函数的关系,以及在结构体中的应用,是成为熟练 C 语言程序员的必经之路。虽然挑战重重,但掌握指针将增强编程效率和灵活性。不断实践和学习,我们将驾驭指针,探索更广阔的编程世界。
|
7天前
|
存储 C语言
C语言进阶---------作业复习
C语言进阶---------作业复习
|
7天前
|
存储 Linux C语言
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)-2
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)
|
7天前
|
自然语言处理 Linux 编译器
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)-1
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)
|
7天前
|
存储 编译器 C语言
C语言进阶第十课 --------文件的操作-1
C语言进阶第十课 --------文件的操作
|
7天前
|
存储 程序员 C语言
C语言进阶第九课 --------动态内存管理-2
C语言进阶第九课 --------动态内存管理
|
7天前
|
编译器 C语言
C语言进阶第九课 --------动态内存管理-1
C语言进阶第九课 --------动态内存管理