【C语言】指针数组测试题(1万字长文)(下)

简介: 【C语言】指针数组测试题(1万字长文)(下)

五六题

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

输出的结果是什么?

分析:首先定义了一个二维数组a,有定义了一个数组指针要十分的注意这个数组指针指向的数组看作是4个元素的。p这个指针变量存放的a,a又代表着二维数组数组第一行的地址。

  • &p[4][2]:&* ( *(p+4)+2),p的类型是数组指针+4只能跳过4个元素的数组,这里一行是5个元素所以跳不完,+4最后在倒数第二行停下,再+2,得到这一行第四个元素的地址,再解引用,由于二维数组没有初始化就得到0。再取出这个元素的地址。
  • &a[4][2]:就是取出最后一行第三个元素的地址。
    &p[4][2] - &a[4][2]:是小地址减去大地址,因为数组随下标的增长地址有低变高。地址相减就相当于指针相减,因为地址就是指针,所以根据指针相减得到的是指针之间的元素个数得到最后结果是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:aa是二维数组数组名对二维数组的数组名取地址就是拿到整个数组的地址,整个数组的地址+1,就跳过整个二维数组。

*(aa + 1):可以写成这样aa[1],相当于第一行的地址+1再解引用得到第二行的地址,aa[1]也就相当于数组名。

七八题

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

输出的结果是什么?

分析:有一个字符指针数组,里面有三个元素,又有一个二级指针存储a的首元素的地址,因为a的首元素是char *类型存储的是字符串的首字符地址。pa++就意味着pa中存储的地址+1,就到了数组的下一个元素,下一个元素是’‘at’'的首字符地址,故输出的是at。

这一题也是最难的一题

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

输出的结果是什么?

分析:有一个字符指针数组。数组的每个元素是相应字符串的首字符地址。

而cp这个二级指针数组存放的是char *类型的地址,刚好c数组的每个元素是char *,最后cpp这个三级指针指向的是二级指针数组的首元素地址。

  • printf("%s\n", **++cpp);,首先cpp先永久+1,也就是移动char ***个步长也就是1,得到指向c+2地址处,再解引用得到c+2,而c+2是c这个数组中的地址,再解引用得到"POINT"。

    -*-- * ++cpp + 3:首先我们还是要明确理解的顺序,先cpp永久+1,再解引用,得到c+1,而c+1是c数组中的地址,然后再–,所以改变了c+1的值变成了c,然后再解引用得到"E"的地址,然后再加3,这时候就代表着"ENTER"这个字符串加3,ENTER我们可以理解成就是E的地址再+3,结果就得到"ER"。
    就相当于:
int main()
{
  printf("%s", "abcde" + 3);
}

*cpp[-2] + 3:首先我们拆解一下,* (*(cpp-2))+3,首先cpp-2,但是不是永久的,然后再解引用,上面我们cpp指向的是下标为2的位置,现在应该指向0,解引用得到c+3,再解引用得到F的地址,F的地址+3得到"ST";

cpp[-1][-1] + 1:首先还是拆解一下,* (*(cpp-1)-1)+1,cpp-1指向c+2,解引用得到c+2,c+2然后要-1得到c+1,c+1解引用得到"NEW",再+1输出"EW"。

总结😈

这篇博客篇幅较长是因为先要深入的理解数组与地址与指针的关系是不太容易的,所以我们需要题目来练习,在数组方面我们让大家理解了数组名±或者&的一些差异,也包括一些类型的不同,指针方面也比较全面是各种类型的杂糅为的就是锻炼自己的理解能力。 完(๑′ᴗ‵๑)

目录
相关文章
|
6天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
18 3
|
18天前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
44 0
|
5天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
13 2
|
14天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
23 1
|
20天前
|
存储 编译器 C语言
【c语言】数组
本文介绍了数组的基本概念及一维和二维数组的创建、初始化、使用方法及其在内存中的存储形式。一维数组通过下标访问元素,支持初始化和动态输入输出。二维数组则通过行和列的下标访问元素,同样支持初始化和动态输入输出。此外,还简要介绍了C99标准中的变长数组,允许在运行时根据变量创建数组,但不能初始化。
35 6
|
17天前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
13 2
|
18天前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
18天前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
24天前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
24天前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。