Size: a a a

2021 March 15

MK

Mikhail Kalugin in pro.cxx
Ofee
А вы сможете доказать, что правила C здесь не перекрыты вышеуказанным пунктом стандарта и, более того, что эти правила действительно позволяют итерироваться по массиву? В таком случае, они однозначно заслуживают внимание, однако никто пока ещё не смог привести этих правил
Да, массив в памяти непрерывная сущность, это все что гарантирует стандарт.
источник

O

Ofee in pro.cxx
Mikhail Kalugin
Да, массив в памяти непрерывная сущность, это все что гарантирует стандарт.
Это справедливо и для C++ и никак не вступает в противоречие с аргументами против возможности итерироваться по двумерному массиву через указатель на инт
источник

BU

Boris Usievich in pro.cxx
взятие адреса массива (он же адрес первого элемента)  подразумевает возможный доступ ко всему массиву. Если компилятор имеет полную информацию, что к какой-то части массива доступа никогда нет - имеет полное право выкинуть. Но это никак не связано с исходным вопросом.
источник

O

Ofee in pro.cxx
Boris Usievich
взятие адреса массива (он же адрес первого элемента)  подразумевает возможный доступ ко всему массиву. Если компилятор имеет полную информацию, что к какой-то части массива доступа никогда нет - имеет полное право выкинуть. Но это никак не связано с исходным вопросом.
Верно. Однако, элементом двумерного массива является массив, а не инт, адрес которого мы берём
источник

O

Ofee in pro.cxx
Ofee
Верно. Однако, элементом двумерного массива является массив, а не инт, адрес которого мы берём
А поскольку адрес двумерного массива или одномерного массива мы не передаём во вне – компилятор видит, что используется только тот массив, адрес элемента которого мы взяли
источник

O

Ofee in pro.cxx
Ofee
А поскольку адрес двумерного массива или одномерного массива мы не передаём во вне – компилятор видит, что используется только тот массив, адрес элемента которого мы взяли
Согласно стандарту, вы не можете свободно прыгать через слой абстракции
источник

BU

Boris Usievich in pro.cxx
согласно стандарту layout многомерных массивов строго определен. Теперь вопрос: а зачем?
источник

AG

Andrey Glebov in pro.cxx
Boris Usievich
согласно стандарту layout многомерных массивов строго определен. Теперь вопрос: а зачем?
ну например можно через memcpy его скопировать в одномерный массив, или записать в файл, итд
даже проитерировать по нему через char *
источник

O

Ofee in pro.cxx
Boris Usievich
согласно стандарту layout многомерных массивов строго определен. Теперь вопрос: а зачем?
А "зачем" – другой вопрос

И, как я указал выше, в этом месте такая трактовка стандарта нарушает нормы здравого смысла

Но если это является проблемой для вас – правильный выход не в том, чтобы закрыть глаза и сказать "я верю в отсутствие UB в этом случае" – а поучаствовать либо в исправлении стандарта, либо поиске других, более верных трактовок, которые могут закрыть эту проблему
источник

BU

Boris Usievich in pro.cxx
Кстати забавно, скопировать через memcpy можно, и юзать как одномерный потом. компилятор при этом имеет право соптимизировать memcpy и к чему мы приходим?
источник

AG

Andrey Glebov in pro.cxx
к bit_cast)
источник

O

Ofee in pro.cxx
Boris Usievich
Кстати забавно, скопировать через memcpy можно, и юзать как одномерный потом. компилятор при этом имеет право соптимизировать memcpy и к чему мы приходим?
Нельзя его потом юзать как одномерный. Вы должны его скастить к исходному типу

P.S. вероятно, моё утверждение является ошибкой
источник

BU

Boris Usievich in pro.cxx
на мой взгляд это мутное место в стандарте, и его надо править, чтобы  такая простая вещь работала. В том числе и в constexpr.
источник

A

Anton in pro.cxx
да и в С написано тоже самое

Successive subscript operators designate an element of a multidimensional array object.
If E is an n-dimensional array (n ≥ 2) with dimensions i × j × . . . × k, then E (used as
other than an lvalue) is converted to a pointer to an (n − 1)-dimensional array with
dimensions j × . . . × k.
источник

A

Anton in pro.cxx
из того, что многомерные массивы копируют с помощью memcpy совсем не значит, что это соответствует стандарту
источник

AG

Andrey Glebov in pro.cxx
Ofee
Нельзя его потом юзать как одномерный. Вы должны его скастить к исходному типу

P.S. вероятно, моё утверждение является ошибкой
int a[3][5]{};
int b[15];
std::memcpy(&b, &a, sizeof b);

а почему нельзя теперь использовать b?
источник

BU

Boris Usievich in pro.cxx
Andrey Glebov
int a[3][5]{};
int b[15];
std::memcpy(&b, &a, sizeof b);

а почему нельзя теперь использовать b?
Видимо можно, но без constexpr это не нужно, а с constexpr memcpy не скомпилируется
источник

AG

Andrey Glebov in pro.cxx
ну в constexpr да, нельзя сделать reinterpret_cast<unsigned char *>, но это вроде не UB
unsigned char всё алиазит же)
источник

BU

Boris Usievich in pro.cxx
Там вообще reinterpret не работает, любой
источник

O

Ofee in pro.cxx
Andrey Glebov
int a[3][5]{};
int b[15];
std::memcpy(&b, &a, sizeof b);

а почему нельзя теперь использовать b?
Я могу ошибиться, но здесь, всё же, нарушается strict aliasing rule, до тех пор, пока мы не сделаем так:
std::memcpy(
 static_cast<unsigned char*>(&b),
 static_cast<unsigned char*>(&a),
 sizeof b);
поскольку std::memcpy принимает void*, а не unsigned char*
Но это не точно, и как трактовать код с точки зрения стандарта, если "исправить" это — я не знаю
источник