📜  C / C++中的多维指针算法

📅  最后修改于: 2021-05-25 23:00:36             🧑  作者: Mango

在C / C++中,除了类型信息外,数组和指针具有相似的语义。

例如,给定一个3D阵列

int buffer[5][7][6];

位置为[2] [1] [2]的元素可以作为“ buffer [2] [1] [2] ”或*(*(*(*(buffer + 2)+ 1)+ 2)进行访问

遵守以下声明

T *p; // p is a pointer to an object of type T

当指针p指向类型T的对象时,表达式* p的类型为T。例如, buffer的类型为5个二维数组。表达式* buffer的类型是“数组数组(即二维数组)”。

基于以上概念,逐步翻译表达式*(*(*(buffer + 2)+1)+ 2)使其更加清晰。

  1. 缓冲区–由5个二维数组组成的数组,即其类型为“由5个二维数组组成的数组”。
  2. buffer + 2 – 5个二维数组中第3个元素的位移。
  3. *(buffer + 2) –解引用,即它的类型现在是二维数组。
  4. *(buffer + 2)+1-位移以访问7个一维数组中的第二个元素。
  5. *(*(buffer + 2)+1) –解引用(访问),现在表达式“ *(*(buffer + 2)+1) ”的类型是整数数组。
  6. *(*(buffer + 2)+1)+ 2 –位移以使元素在整数的一维数组中的第3个位置。
  7. *(*(*(buffer + 2)+ 1)+ 2) –在第3个位置访问元素(整个表达式类型现在为int )。

编译器计算“偏移量”以访问数组元素。 “偏移”是根据数组的尺寸计算的。在上述情况下, offset = 2 *( 7 * 6 )+1 *( 6 )+ 2蓝色是尺寸,请注意,较高的尺寸未在偏移量计算中使用。在编译期间,编译器会知道数组的维数。使用offset,我们可以访问元素,如下所示,

element_data = *( (int *)buffer + offset );

并非总是可以在编译时声明数组的维数。有时我们需要将缓冲区解释为多维数组对象。例如,当我们处理尺寸在运行时确定的3D图像时,不能使用常规的数组下标规则。这是由于在编译时缺少固定的尺寸。考虑以下示例,

int *base;

其中base指向大型图像缓冲区,该缓冲区表示尺寸为lxbxh的3D图像,其中l,b和h为变量。如果要访问位置(2、3、4)的元素,则需要将元素的偏移量计算为

offset = 2 *(bxh)+ 3 *(h)+ 4并且元素位于base + offset

进一步概括,给定大小为[ lxbxh ]尺寸的数组的起始地址(例如base ),我们可以通过以下方式在任意位置(a,b,c)访问元素,

数据= *(base + a *( bxh )+ b *( h )+ c); //注意,我们没有使用更高的维度l

相同的概念可以应用于任何数量的尺寸。我们不需要更高的维度来计算多维数组中任何元素的偏移量。这是我们将多维数组传递给函数时省略较高维的原因。仅当程序员迭代有限数量的较高维元素时,才需要较高维。

AC / C++难题,预测以下程序的输出

int main()
{
    char arr[5][7][6];
    char (*p)[5][7][6] = &arr;
  
    /* Hint: &arr - is of type const pointer to an array of
       5 two dimensional arrays of size [7][6] */
  
    printf("%d\n", (&arr + 1) - &arr);
    printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
    printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
    printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
  
    return 0;
}

输出:

1个

210

42

210

感谢学生指出错误。

要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”