памяти линейно?
Не сдвинемся ли мы просто на следующую строку?
потому что в стандарте так написано что это уб
Есть шанс что памяти не будет, например
всмысле не будет?
как её там не будет, если мы создали двумерный массив?
так а что именно? мы просто ссылаемся на начало массив и двигаемся сколько нам нужно?
А, я не посмотрел на изначальный пример. Ну, в любом случае в стандарте такая адресация запрещена
https://godbolt.org/z/78KWfsq7o
Тут начинается ОЧЕНЬ длинный спор на эту тему
а что это значит? я просто с телефона
а если по другому написать, *(ptr + length*row_count + in_row_number), че на это скажешь?)
constexpr int f() { int a[3][3] = {}; return a[0][5]; } <source>:1:15: error: constexpr function never produces a constant expression [-Winvalid-constexpr] constexpr int f() { ^ <source>:3:12: note: cannot refer to element 5 of array of 3 elements in a constant expression return a[0][5];
так а если одним словом, то итог какой? я просто ответил, что UB, но не уверен
я просто не понимаю - и что это значит?
Скажу, что валидно адресоваться только в рамках строчек по ptr
это фактически одно и тоже
Это значит, что в компайл-тайме нет уб Только ошибки компиляции
ну а в рантайме?
constexpr проверил - UB есть
Значит уб
ооо, найс👍🏻
вот поэтому и надо знать, есть ли в стандарте си где нибудь "a[n][m] всегда реализуется как последовательная память ..."
При чём тут это? Это и в стандарте С++ есть
и что, С++ меняет как сделаны в си подобные массивы? Если да, то нужно С++ смотреть, если нет, то не нужно
Ну например в С++ нет vla, в Си — есть Уже что-то, но сломал
В стандарте С++ есть, что массивы реализованы как линейна память. И есть то, что такая адресация уб
Всегда надо смотреть в С++ стандарт, если ты про С++ говоришь
Не хочу повторять этот спор заново
ты путаешь стандарт и реализацию стандарта, стандарт дает гарантии сверху, компиляторы вряд ли будут после написания си компилятора менять реализацию в плюсовом компиляторе, но теоретически может, стандарт не запрещает. Спор о гарантиях которые дает стандарт, а не о реализациях
Не, он не путает Просто он подумал что массивы в С++ полностью скопипащщены из стандарта Си
Выходить за границы массива нельзя. Подмассив тоже является массивом, поэтому за его границы тоже нельзя вне зависимости от того, есть там следующий подмассив, или нет. Компилятор гипотетически (но только гипотетически) может увидеть, что мы напрямую не обращаемся к подмассивам a[1] и a[2] и удалить их, оставив только a[0]
сомнительное утверждение что стандарт С++ дает такую гарантию
И в стандарте C++ было, вроде, это не отменяет того, что так нельзя
если было, то что значит нельзя? что может привести к UB?
К UB приводят слова из стандарта
Вы же не рассчитываете, что компилятор выделит память под неиспользованную переменную? В коде a[0][5] тоже ни a[1], ни a[2] не использованы, почему компилятор должен был выделить драгоценную память под них?
смысле неиспользованную?
Вы используете в коде только a[0]
а если буду всё использовать, то что будет?
я подразумевал, что всё используется, если это на что-то влияет.
факт использования не отменяет UB, а уменьшает вероятность, что будет минус нога
Это ничего не меняет. Я указал, как гипотетически ваш код может взорваться. То, что вы используете все элементы не изменит формулировку стандарта
Походу, в универе не считают, что там UB - можете ткнуть в стандарт, чтобы я смог проапеллировать ))
Естественно, не считают. На моей памяти практически каждый достаточно взрослый препод считает своим долгом рассказать, что память линейная и что по многомерным массивам можно ходить как угодно. P.S. В стандарт не ткну
Можете попробовать
Ооо, спасибо
А если написать a[0][5], то не будет ли там каст к поинтеру после чего это становится валидным?
то есть array to pointer decay
Допустим, int* p = a[0]; Тогда p + 5 эквивалентно a[0][5]. Подставим все значения в неравенство из стандарта 0 ≤ i + j ≤ n, где i — это элемент массива (в нашем случае нулевой, поскольку p приводится к нему), j — это наше смещение на 5, а n — размер массива: 0 ≤ 0 + 5 ≤ 3. Что-то не сходится. С пунктом выше тоже не сходится, наш p — не нулевой указатель. Остаётся третий вариант: the behavior is undefined
хм, а на что будет указывать a[0] - разве на массив из 3-х эллементов?
и это рассуждение не валидно?
Хотя вы и скрыли информацию о размере, после преобразования массива к int*, (*p) не перестаёт быть элементом исходного массива (просто потому что адресная арифметика в принципе применима только к указателям на элементы массива). А массивы всегда имеют некоторый размер n. И никакой факт преобразования не может изменить этот n
Обсуждают сегодня