Treating 2D array as 1D array

后端 未结 4 1928
余生分开走
余生分开走 2020-12-10 12:31

Let\'s say we have a 2D int array:

int a[3][4] = { { 1,3,2,4 }, { 2,1,5,3 }, { 0,8,2,3 } };

Is it legal and valid to take its

4条回答
  •  隐瞒了意图╮
    2020-12-10 12:49

    A 2D array cannot be treated as a 1D array

    As noted by @KillzoneKid, the address of an array is not pointer interconvertable with that of the first element even though they share the same address value.

    constexpr provides a convenient way to evaluate UB. Compilers are required to detect UB when constexprs are evaluated. Thus a simple test can be made. This function, when evaluated during compile time will detect accessing values beyond an array's range.

    // sum "n" sequential ints
    constexpr int sum(const int* pi, int n) {
        int sum = 0;
        while (n-- > 0)
            sum += *pi++;
        return sum;
    };
    

    When this is called at runtime with a pointer to the first element of a 1D or 2D array it will sum the elements but is UB if "n" goes beyond the boundary of the array. For a 2D array, this would be the extent of the lowest dimension. Not the size of the whole array.

    Examining different instances of a pointer to an int we can see UB occurs once we try to access a value beyond the array dimension.

    int main()
    {
        constexpr int i0{1};
        constexpr int i1[2]{ 1,2 };
        constexpr int i2[2][2] = { { 1,2}, {3,4} };
    
        constexpr int sum0 = sum(&i0, 1);       // fails for n>1
        constexpr int sum1 = sum(&i1[0], 2);    // fails for n>2
        constexpr int sum2 = sum(&i2[0][0], 2); // fails for n>2
        const int sum3 = sum(&i2[0][0], 4);     // runtime calc, UB. fails if constexpr
    
        return sum0 + sum1 + sum2 + sum3;       // 17
    }
    

    For accesses beyond existing data, such as in sum0 and sum1, UB is clear. But sum2 points to existing data for n=[0:3) yet constexpr evaluation shows it to be UB for n=4.

    I was somewhat surprised to learn this. Every compiler I've ever used worked as expected when doing things like scaling all the coefficients of a matrix by a fixed amount. But I can see rationales based on optimization assumptions that portions of a matrix won't change from the result of a function call on another part not in the same array sequence.

提交回复
热议问题