MST

星途 面试题库

面试题:C语言数组指针转换的复杂场景及陷阱

在C语言中,考虑以下代码片段:`int (*p)[5] = &(int [5]){1, 2, 3, 4, 5};` 详细解释这段代码的含义,包括指针`p`的类型、初始化过程以及如何通过`p`安全地修改数组元素。另外,阐述在这种复杂的数组指针转换场景下,可能会出现的内存访问错误及其原因,并如何避免。
35.7万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
  1. 指针p的类型
    • p是一个指针,它指向一个包含5个int类型元素的数组。即p的类型是int (*)[5],这种类型被称为数组指针。
  2. 初始化过程
    • (int [5]){1, 2, 3, 4, 5}是一个临时的匿名数组,它创建了一个包含5个int类型元素的数组,并初始化其值为{1, 2, 3, 4, 5}
    • &(int [5]){1, 2, 3, 4, 5}取这个匿名数组的地址。
    • int (*p)[5] = &(int [5]){1, 2, 3, 4, 5};将这个匿名数组的地址赋值给指针p,从而完成了p的初始化。
  3. 通过p安全地修改数组元素
    • 由于p指向一个包含5个int类型元素的数组,可以通过指针运算来访问和修改数组元素。例如:
    #include <stdio.h>
    int main() {
        int (*p)[5] = &(int [5]){1, 2, 3, 4, 5};
        (*p)[2] = 10; // 修改数组的第3个元素
        for(int i = 0; i < 5; i++) {
            printf("%d ", (*p)[i]);
        }
        return 0;
    }
    
    • (*p)解引用指针p,得到指向的数组,然后使用[2]来访问数组的第3个元素并赋值为10。
  4. 可能出现的内存访问错误及其原因
    • 越界访问
      • 原因:如果使用(*p)[i]访问数组元素时,i的值小于0或者大于等于5(数组长度),就会发生越界访问。例如(*p)[-1](*p)[5],这会导致未定义行为,因为访问了不属于该数组的内存区域。
    • 悬空指针
      • 原因:如果在p指向的匿名数组的生命周期结束后(例如匿名数组在一个函数内部创建,函数返回后),仍然使用p来访问数组元素,就会产生悬空指针问题。因为此时p指向的内存已经无效。
  5. 如何避免
    • 避免越界访问
      • 在访问数组元素前,确保索引值在合法范围内。可以使用条件判断来检查索引,例如:
      int index = 2;
      if(index >= 0 && index < 5) {
          (*p)[index] = 20;
      }
      
    • 避免悬空指针
      • 如果是在函数内部创建匿名数组并赋值给p,确保p的使用范围在数组的生命周期内。或者可以使用动态内存分配(如malloc)来创建数组,这样可以更好地控制数组的生命周期。例如:
      int *arr = (int *)malloc(5 * sizeof(int));
      for(int i = 0; i < 5; i++) {
          arr[i] = i + 1;
      }
      int (*p)[5] = (int (*)[5])&arr;
      // 使用完后记得释放内存
      free(arr);
      
    • 这种方式下,通过malloc分配的内存可以在需要时手动释放,避免了悬空指针问题。