Одномерный доступ к многомерному массиву: это четко определенное поведение?

Я полагаю, мы все согласны с тем, что это считается идиоматическим C для доступа к истинному многомерному массиву путем разыменования (возможно, смещения) указателя на его первый элемент одномерным способом, например:

void clearBottomRightElement(int *array, int M, int N)
{
    array[M*N-1] = 0;  // Pretend the array is one-dimensional
}


int mtx[5][3];
...
clearBottomRightElement(&mtx[0][0], 5, 3);

Однако языковой юрист во мне нуждается в убеждении, что это на самом деле четко определенный C! В частности:

  1. Гарантирует ли стандарт, что компилятор не будет вставлять отступы между ними, например mtx [0] [2] и mtx [1] [0] ?

  2. Обычно индексация с конца массива (кроме одного за концом) выполняется undefined (C99, 6.5.6 / 8). Таким образом, следующее явно не определено:

     struct {
      int row [3];  // Рассматриваемый объект - это int [3]
      int other [10];
     } foo;
    int * p = & foo.row [7];  // ОШИБКА: грубая попытка получить & foo.other [4];
     

    Таким образом, по тому же правилу можно ожидать, что следующее будет неопределенным:

     int mtx [5] [3];
    int (* строка) [3] = & mtx [0];  // Рассматриваемый объект по-прежнему является int [3]
    int * p = & (* строка) [7];  // Почему это лучше?
     

    Так почему это должно быть определено?

     int mtx [5] [3];
    int * p = & (& mtx [0] [0]) [7];
     

Так какая часть стандарта C явно разрешает это? (Давайте предположим для обсуждения.)

РЕДАКТИРОВАТЬ

Обратите внимание, что я не сомневаюсь, что это отлично работает во всех компиляторах. Я спрашиваю, разрешено ли это явно стандартом.

16
задан Sourav Ghosh 27 December 2017 в 15:51
поделиться