【问题标题】:End of multi-dimensional array using compact pointer notation使用紧凑指针表示法结束多维数组
【发布时间】:2011-01-12 21:39:44
【问题描述】:

对于 4-D 数组,我尝试使用紧凑指针表示法对值进行平均。使用我的文本中的示例,它说我可以使用这样的东西:

void DisplayAverage(double (*set)[DIM1][DIM2][DIM3])
    double *ptr;
double subTotal2 = 0; 
    for (ptr = (double *)set; ptr < (double *)set + DIM0 * DIM1 * DIM2 * DIM3; ptr++) {
    subTotal2 += *ptr;
    subTotal2 /= (DIM0 * DIM1 * DIM2 * DIM3); 
cout << "Using compact pointer operations, total: " << subTotal2 << "\n";
    }
}

该代码有效。但是,如果我尝试使用文本中的另一种表示法:

for (ptr = (double *)set; ptr < (double *)(&set + 1); ptr++) {

要访问数组,我没有得到任何输出。有什么想法吗?谢谢。

【问题讨论】:

  • 用附加的编程语言“C++”重新标记 - 它看起来确实像 C++,如果不是,请更正。

标签: c++ pointers


【解决方案1】:

你的地址太多了:

// notice: "set" instead of "&set"
for (ptr = (double *)set; ptr < (double *)(set + DIM0); ptr++) {

您在参数的地址上加一(因此指向无处),而不是 DIM0 到参数的值(这将带您到数组数据之后,这是您的目标)。

请注意,参数是指向维度数组[DIM1][DIM2][DIM3] 的指针。换句话说,您传递给函数的参数可以是double[DIM0][DIM1][DIM2][DIM3] 类型的数组,它将衰减为该参数的指针类型。您有DIM0 行,因此您将DIM0 添加到该指针以到达最后一个单元格之后的位置。

您可能想到的是在指向整个数组的指针上加一。如果您有以下声明,这将起作用。

void DisplayAverage(double (*set)[DIM0][DIM1][DIM2][DIM3]);

您现在需要使用&amp;arg 而不仅仅是arg 来传递参数,以实际传递数组的地址,而不是让它衰减到它的内部维度类型。然后循环可以写成

for (ptr = (double *)set; ptr < (double *)(set + 1); ptr++) {

【讨论】:

    【解决方案2】:

    如果 set 是一个数组,您的表达式 (&amp;set + 1) 将指向数组的过去,但它不是。变量 set 是变相的指针(不是数组),就像所有看起来像按值传递的数组一样。

    更好的例子:

    void g(int a[3]);
    // exactly the same as:
    void g(int* a);
    // note the 3 is ignored by the compiler here! it serves as documentation when
    // reading the code, but nothing else, and for this reason you should pretty much
    // always drop it, preferring:
    void g(int a[]); /*or*/ void g(int* a); // (which are also identical)
    
    void f() {
      int a[3] = {0, 1, 2};
      int* end = (int*)(&a + 1); // &a has type int (*)[3] (that's pointer to array
      // of 3 ints so &a + 1 has the same value as &a[2] + 1 ("one past" the last
      // valid item in a)
    
      int* p = a; // this is how a is passed "by value" to a function such as g
      end = (int*)(&p + 1); // even though this "looks" the same, &p has type int**
      // and adding 1 to that has no correlation with what p points to.
      // to make matters worse, the cast (and C++-style casts have the same problem
      // here) hides this type error and makes the compiler believe we know what
      // we're doing
    
      // pointers are not arrays, even though they mostly behave similarly:
      std::cout << sizeof(a) << ", " << sizeof(p) << ", " << sizeof(void*) << '\n';
      // compare the int* size to void* size
    }
    

    以及将其应用于指向数组的指针的示例:

    typedef int T[3];
    void g(T a[3]);
    // same as:
    void g(T a[]); /*and*/ void g(T* a);
    
    // that T happens to be an array type doesn't change anything, these are
    // also declaring the same function:
    void g(int a[][3]); /*and*/ void g(int (*a)[3]);
    
    void f() {
      int a[3][3] = {};
      int* end = (int*)(&a + 1);
      // note that end - &a[0][0] is 9
    
      int* p = &a[0][0];
    
      std::cout << sizeof(a) << ", " << sizeof(p) << ", " << sizeof(void*) << '\n';
    }
    

    【讨论】:

      【解决方案3】:

      我建议不要在 C++ 中使用静态多维数组。在How to initialize 3D array in C++中查看我的回复

      【讨论】:

        猜你喜欢
        • 2011-01-05
        • 1970-01-01
        • 2021-12-24
        • 1970-01-01
        • 1970-01-01
        • 2017-10-09
        • 1970-01-01
        • 2016-09-15
        • 1970-01-01
        相关资源
        最近更新 更多