Законность кода

Рассмотрите следующий код:

void populate(int *arr)
{
   for(int j=0;j<4;++j)
       arr[j]=0;
}

int main()
{
   int array[2][2];
   populate(&array[0][0]);
}

Было обсуждение относительно этого на местном сообществе, действителен ли код или не (Я, как предполагается, упоминаю его имя?). Один парень говорил, что это вызывает UB, потому что это нарушает

Стандарт C++ ($5,7/5 [expr.add])

"Если и операнд указателя и результат укажут на элементы того же объекта массива или одно прошлое последний элемент объекта массива, то оценка не должна производить переполнение; иначе поведение не определено".

Но я не вижу ничто плохого с кодом, код совершенно хорошо для меня.

Так, я просто хочу знать, что этот код действителен или нет? Я пропускаю что-то?

14
задан Charles 29 October 2012 в 16:32
поделиться

4 ответа

Ваш массив - две массивы INT [2] , в то время как ваша функция заполняет () как один массив int [4] . В зависимости от того, как именно то, как компилятор решает выровнять элементы массива , это может быть не допустимое предположение.

В частности, когда j j 2, и вы пытаетесь получить доступ ART [2] , это за пределами Main массива [0] и поэтому недействителен.

15
ответ дан 1 December 2019 в 10:02
поделиться

Это не всегда сработает. В C есть массивы массивов, а не 2D массивы. В данном конкретном примере, я подозреваю, что он работает корректно, не всегда указывается, что массивы должны быть смежными в памяти (статические массивы могут быть, проверьте стандарт C/C++). Однако, если бы вы динамически выделяли передаваемую память, то, скорее всего, это было бы неудачно, так как malloc(или new), возможно, разместил бы подмассивы достаточно далеко друг от друга.

Если же вы хотите линейно перемещаться по памяти '2d', вы можете сконструировать 2D доступ к 1D массиву, и он будет работать нормально, а такие вещи, как memset, будут работать и с 1D массивом.

3
ответ дан 1 December 2019 в 10:02
поделиться

У вас есть массив массивов. Массив [1] следует массива [0] в памяти, потому что массивы смеются. Если p == массив [0] , то p [1] следует p [0] , потому что массивы смеются. Итак, вы правы: все память для массива является смежным.

На картинках Array выглядит так.

+-----------------+-----------------+
|      [0]        |      [1]        |
+-----------------+-----------------+

Теперь давайте сломаемся массив [0] и Array [1] , они индивидуально выглядят так:

+--------+--------+
|  [0]   |  [1]   |        
+--------+--------+

Итак, окончательная картина:

+--------+--------+--------+--------+
| [0][0] | [0][1] | [1][0] | [1][1] |
+--------+--------+--------+--------+

сейчас Вопрос в том, можете ли вы получить доступ к этой смежной памяти, как вы находитесь. Ответ, Это не гарантируется стандартом . Массивы смежные, но стандарт не позволяет индексировать способ, которым вы сделали. Другими словами:

и массив [0] [0] +2 == & Array [1] [0] , но (& a [0] [0] + 2) + 1 undefined, тогда как & A [1] [0] + 1 действителен. Если это кажется странным, то есть, но согласно цитату, которую вы разместили из стандарта, вам разрешено рассчитать указатель, который находится внутри массива, либо в большинстве прошедших массив (без размытия того, что «один прошлый» указатель) Отказ

На практике я сомневаюсь, что это никуда не удастся, но, по крайней мере, в соответствии со стандартом, ваш код недействителен из-за неопределенного поведения.

См. Это пост на COMP.LANG.C также.

9
ответ дан 1 December 2019 в 10:02
поделиться

В C все хранится в линейных сегментах памяти. Вы передаете адрес a[0][0], который совпадает с адресом a[0], поэтому a[i][j] такая же, как a[i*ColSize+j], потому что все хранится линейно. Но если бы вы выделяли память динамически, то это было бы неудачно, потому что в это время все строки могли бы не храниться в смежном месте. Тогда a[i][j] было бы *(&a[i]+j).

0
ответ дан 1 December 2019 в 10:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: