Size: a a a

2021 March 14

O

Ofee in pro.cxx
Mikhail Kalugin
Короче, все уприрается в гарантию, что массив (в том числе массив массивов) это непрерывный кусок памяти.
Нет же. Сомнений в этом ни у кого нет. Проблема в том, имеет ли компилятор формальное право заложиться, что при доступе по arr[0][X] не произойдет доступ к arr[1][Y]. И пока что только здравый смысл запрещает компиляторами делать на основе этого неочевидные оптимизации, вроде примера приведенного в чате выше, он может захотеть инициализировать нулем только arr[0], оставив arr[1] неинициализированным, поскольку формально к arr[1] в теле функции никто не мог обратиться через p:
void foo() {
   int arr[3][5] = {0};
   int * p = arr[0][0];
   // use p
}
источник

VS

Vlad Serebrennikov in pro.cxx
здорово
вечно забываю про constexpr в таких обсуждениях
источник

IS

I S in pro.cxx
Ofee
Нет же. Сомнений в этом ни у кого нет. Проблема в том, имеет ли компилятор формальное право заложиться, что при доступе по arr[0][X] не произойдет доступ к arr[1][Y]. И пока что только здравый смысл запрещает компиляторами делать на основе этого неочевидные оптимизации, вроде примера приведенного в чате выше, он может захотеть инициализировать нулем только arr[0], оставив arr[1] неинициализированным, поскольку формально к arr[1] в теле функции никто не мог обратиться через p:
void foo() {
   int arr[3][5] = {0};
   int * p = arr[0][0];
   // use p
}
https://eli.thegreenplace.net/2015/memory-layout-of-multi-dimensional-arrays

Хорошая статья есть на эту тему, вообще если массив на стеке то по дефолту row-major
источник

BU

Boris Usievich in pro.cxx
хе-хе. Стоит убрать constexpr и  consteval и все компилируется
источник

IS

I S in pro.cxx
Если я правильно понимаю о какой оптимизации речь
источник

LA

Liber Azerate in pro.cxx
Boris Usievich
хе-хе. Стоит убрать constexpr и  consteval и все компилируется
Логично. Почему? Потому что в constexpr-контексте запрещены уб и компилятор обязан не скомпилировать это. Вне constexpr-контекста такой обязанности нет
источник

BU

Boris Usievich in pro.cxx
ээээ, нет. Это либо ошибка либо нет.  причем вполне себе дает ожидаемый результат https://godbolt.org/z/Gj4YdE
источник

IS

I S in pro.cxx
Boris Usievich
хе-хе. Стоит убрать constexpr и  consteval и все компилируется
Стоит убрать GCC и проблем вообще нет :)
источник

LA

Liber Azerate in pro.cxx
Boris Usievich
ээээ, нет. Это либо ошибка либо нет.  причем вполне себе дает ожидаемый результат https://godbolt.org/z/Gj4YdE
источник

BU

Boris Usievich in pro.cxx
То есть по вашему компилятор видит UB, но не дает даже предупреждения если это не constexpr?
источник

O

Ofee in pro.cxx
I S
https://eli.thegreenplace.net/2015/memory-layout-of-multi-dimensional-arrays

Хорошая статья есть на эту тему, вообще если массив на стеке то по дефолту row-major
Я не уверен, что это имеет отношение к моему сообщению. Я лишь предполагаю, что в приведенном выше примере компилятор имеет формальное право не занулять элемены массива начиная с arr[1][0] по arr[2][4] или переиспоььзовать эту память под переменные на стеке
источник

MK

Mikhail Kalugin in pro.cxx
Ofee
Нет же. Сомнений в этом ни у кого нет. Проблема в том, имеет ли компилятор формальное право заложиться, что при доступе по arr[0][X] не произойдет доступ к arr[1][Y]. И пока что только здравый смысл запрещает компиляторами делать на основе этого неочевидные оптимизации, вроде примера приведенного в чате выше, он может захотеть инициализировать нулем только arr[0], оставив arr[1] неинициализированным, поскольку формально к arr[1] в теле функции никто не мог обратиться через p:
void foo() {
   int arr[3][5] = {0};
   int * p = arr[0][0];
   // use p
}
Немного не тот случай в общем, и int *p = arr[0]; наверное... И спор ушел, гм, немного вбок. Получение указателя на весь массив int *p = arr; дает первый элемент, но память непрерывная и, в принципе, можно получить любой элемент если понимать как они расположены в памяти.
источник

LA

Liber Azerate in pro.cxx
Boris Usievich
То есть по вашему компилятор видит UB, но не дает даже предупреждения если это не constexpr?
Если это ill-formed код, то компилятор обязан предоставить диагностику, пока это не ifndr. Но ill-formed и ub не тождественны.
источник

LA

Liber Azerate in pro.cxx
Boris Usievich
То есть по вашему компилятор видит UB, но не дает даже предупреждения если это не constexpr?
Строго говоря, компилятор не видит UB. Если бы он везде проверял код на отсутствие UB, это было бы жутко медленно. В constexpr-контексте же компилятор обязали проверять, да
источник

O

Ofee in pro.cxx
Mikhail Kalugin
Немного не тот случай в общем, и int *p = arr[0]; наверное... И спор ушел, гм, немного вбок. Получение указателя на весь массив int *p = arr; дает первый элемент, но память непрерывная и, в принципе, можно получить любой элемент если понимать как они расположены в памяти.
Да нет, это то, с чего начался спор

Да, память непрерывная, всё так, но компилятор может заключить, что она не вся используется и... выкинуть лишний код для инициализации или переиспользовать эту память. Или бросить исключение при доступе к ней
источник

AG

Andrey Glebov in pro.cxx
Ещё может быть такое, что компиляторы специально не пытаются такое оптимизировать - ради совместимости с неправильным кодом.
К примеру, некоторые компиляторы определяют доступ к неактивному члену union (для trivial типов или как-то так), хотя в общем случае это UB.
источник

A

Anton in pro.cxx
Andrey Glebov
Ещё может быть такое, что компиляторы специально не пытаются такое оптимизировать - ради совместимости с неправильным кодом.
К примеру, некоторые компиляторы определяют доступ к неактивному члену union (для trivial типов или как-то так), хотя в общем случае это UB.
👍
источник

MK

Mikhail Kalugin in pro.cxx
Ofee
Да нет, это то, с чего начался спор

Да, память непрерывная, всё так, но компилятор может заключить, что она не вся используется и... выкинуть лишний код для инициализации или переиспользовать эту память. Или бросить исключение при доступе к ней
Здравый смысл и ручное управление памятью - компилятор не должен принимать решения на основе того, что кто-то делает с указателями.
источник

АК

Александр Караев... in pro.cxx
Mikhail Kalugin
Здравый смысл и ручное управление памятью - компилятор не должен принимать решения на основе того, что кто-то делает с указателями.
источник

MK

Mikhail Kalugin in pro.cxx
constexpr же...
источник