С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/21: Рейтинг темы: голосов - 21, средняя оценка - 4.71
3 / 3 / 0
Регистрация: 28.11.2018
Сообщений: 242

Почему работает динамический массив из 0 - элементов

05.02.2019, 22:57. Показов 4572. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток! Столкнулся нечаянно с такой проблемой: создавая динамический массив из нуля элементов - он создается! Да и при этом, могу записать в нулевой элемент, первый элемент, второй - числа(например), а потом он их еще и сохраняет в себе, как будто там не ноль элементов, а гораздо больше и я в свободные ячейки просто что-то записываю. Это..Как так-то вообще? Что за магия?
Т.к. создавая обычный массив НЕ в динам. памяти с 0 - элементами, выдает ошибку - всё верно и логично! (Ну как бы логично, если я создаю "массив" в комнате из нуля коробок, то я ничего не смогу в них положить, т.к. их попросту нет - ноль!)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
    //int arr[0]; - ERROR
    int *p = new int[0];//???
    p[0] = 10;
    p[1] = 5;
    p[2] = 17;
 
    cout << p[0] << endl;
    cout << p[1] << endl;
    cout << p[2] << endl;
 
    return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.02.2019, 22:57
Ответы с готовыми решениями:

Не работает, если массив динамический ?! Почему?
Простая задача, есть текст , удалить из него набор символов, вот код - все работает -&gt; char c...

Создать динамический массив строк, почему не работает?
#include &lt;stdio.h&gt; #include &lt;malloc.h&gt; #include &lt;stdlib.h&gt; void main (void) { char **a; int n, m, i,j; printf(&quot;Vvedite kol-vo...

Почему не работает динамический запрос?
еще один вопросик SqlCeEngine engine = new SqlCeEngine(&quot;Data Source='contacts.sdf';&quot;); SqlCeConnection connection = new...

18
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
05.02.2019, 23:16
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
создавая динамический массив из нуля элементов - он создается
А чего бы ему и не создаться? Стандарт разрешает.
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Да и при этом, могу записать в нулевой элемент, первый элемент, второй - числа(например)
Нет не можете. Доступ к такому указателю UB.
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
а потом он их еще и сохраняет в себе, как будто там не ноль элементов, а гораздо больше и я в свободные ячейки просто что-то записываю
А кто дает гарантию что будет выделено 0 элементов? Компилятор выделит например 1 байт в случае с gcc. Потенциально ОС выделит еще больше тк вызов нативных функций довольно затратный, поэтому весьма вероятно ОС себя перестрахует.
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Это..Как так-то вообще?
Ну, вот так.
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Т.к. создавая обычный массив НЕ в динам. памяти с 0 - элементами, выдает ошибку - всё верно и логично! (Ну как бы логично, если я создаю "массив" в комнате из нуля коробок, то я ничего не смогу в них положить, т.к. их попросту нет - ноль!)
С чего вдруг [] тоже самое что и new[]?
0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
06.02.2019, 01:50
Нюансы синтаксиса: запись double *array - это указатель или что-то иное?
0
3 / 3 / 0
Регистрация: 28.11.2018
Сообщений: 242
06.02.2019, 02:26  [ТС]
Azazel-San,
Цитата Сообщение от Azazel-San Посмотреть сообщение
Нет не можете. Доступ к такому указателю UB.
Почему не могу, если могу? У меня работает...Код тот же что и в шапке.
И что за указатели UB??? Первый раз о таком слышу. Буду благодарен за ответ
Цитата Сообщение от Azazel-San Посмотреть сообщение
А чего бы ему и не создаться? Стандарт разрешает.
А где почитать про конкретно ЭТОТ стандарт? Интересно.
Цитата Сообщение от Azazel-San Посмотреть сообщение
С чего вдруг [] тоже самое что и new[]?
Искал по форумам, в гугле. Что-то не нашел ничего на эту тему. Где об этом почитать?

Буду очень благодарен за ответ!
0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
06.02.2019, 06:08
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
И что за указатели UB???
https://ru.wikipedia.org/wiki/... _поведение
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
А где почитать про конкретно ЭТОТ стандарт?
Стандарт С++, § 5.3.4 New.
Липпман "Язык программирования С++. Базовый курс", 5-е издание, стр.609
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Что-то не нашел ничего на эту тему. Где об этом почитать?
Как добавить объект в массив объектов?
0
 Аватар для COKPOWEHEU
4082 / 2680 / 432
Регистрация: 09.09.2017
Сообщений: 11,900
06.02.2019, 11:22
Цитата Сообщение от Azazel-San Посмотреть сообщение
Нет не можете. Доступ к такому указателю UB.
Записать-то может, но вот к чему это приведет? Если повезет - программа полезет в недоступную память и просто крашнется, если нет... ну, не стоит до этого доводить.
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Да и при этом, могу записать в нулевой элемент, первый элемент, второй - числа(например)
С/С++ не проверяют выход за границы массива, а тем более указателей. Например, есть функция
void bzero(void *s, size_t n)
Она заполняет первые n байтов массива s нулями. Откуда ей знать какой у этого массива размер на самом деле? Собственно, по указателю ей можно передать не только массив, но и переменную, структуру, да что угодно.
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
06.02.2019, 11:43
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Почему не могу, если могу?
Потому что. Само выделение динамического массива из 0 элементов - implementation defined behavior, а полученное значение будет не nullptr указатель, т.е. такой указатель вполне валидный, хоть у вас там и выделялось 0 элементов, но обращение к такому указателю, тем более запись туда чего либо UB.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Если повезет - программа полезет в недоступную память и просто крашнется, если нет...
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
У меня работает...
Это и есть UB. Программа содержащая UB может вполне себе валидно работать, до какого-то момента.
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
А где почитать про конкретно ЭТОТ стандарт?
http://eel.is/c++draft/expr.new#8
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Где об этом почитать?
Сама конструкция уже намекает что это как бы немного разные вещи, хотя и имеют очень много общего.
0
 Аватар для SomniPhobia
602 / 439 / 137
Регистрация: 22.11.2017
Сообщений: 1,408
06.02.2019, 11:45
MJ_PRUTYG, привет!
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
int *p = new int[0];
Напиши такие строки
C++
1
2
int *a = new int[777u];
cout << a[-4] / sizeof(int) << endl;
Что появится на консоле?

Добавлено через 1 минуту
Вот ещё для эксперимента код.
C++
1
2
3
4
5
int *a = new int[10u];
    for (int u = -10; u < 100; ++u)
    {
        cout << u << " " << a[u] << endl;
    }
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
06.02.2019, 11:52
Цитата Сообщение от SomniPhobia Посмотреть сообщение
Напиши такие строки
Какое это имеет отношение к теме?
Цитата Сообщение от SomniPhobia Посмотреть сообщение
Вот ещё для эксперимента код.
0
 Аватар для SomniPhobia
602 / 439 / 137
Регистрация: 22.11.2017
Сообщений: 1,408
06.02.2019, 11:54
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
int *p = new int[n];
Это просто создание указателя с резервацией места в памяти на n позиций.
Механизм подыскивает участок в памяти, где можно зарезервировать n ячеек, идущих монотонно друг за другом. Резервирует его путём прописи маркеров до и после занимаемого участка.
Пусть объявлен массив
int *p = new int[5];
У меня в системе индексации массива на позициях -1 и 5 значение -33686019 (мне интересно, у Вас также). И эти числа неизменны у меня, то есть каждую компиляцию и запуск выходят они не зависимо от длины массива, его обрамляют эти числа.
Если смотреть за пределы выделенной памяти, то там тоже есть ячейки со значениями, причём можно у них спокойно поменять значения и что - то повалить.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
06.02.2019, 12:08
Цитата Сообщение от SomniPhobia Посмотреть сообщение
значение -33686019
Это 0xFDFDFDFD, известное также как `no mans land` (дословно - ничейная земля).
См таблицу: http://www.nobugs.org/develope... html#table
Значение, используемое CRT Microsoft в целях отладки для обозначения динамической памяти недоступной для использования.
1
 Аватар для SomniPhobia
602 / 439 / 137
Регистрация: 22.11.2017
Сообщений: 1,408
06.02.2019, 12:18
MJ_PRUTYG,
int *p = new int[n];
p - указатель на 0 элемент массива.
Если его разыменуем, то получим значение из 0 ячейки массива p[0].
Указатель можно смещать на k позиций памяти. k может быть не только положительным (вперёд), но и отрицательным (назад).
p + k
Смещённый указатель также можно разыменовать и получить значение из ячейки памяти, на которую показывает этот указатель.
*(p + k) эквивалентно p[k]
Сам указатель p не знает размер массива и может свободно ходить по памяти, даже за пределами массива.
Указателю p безразлично, чему равно n в выражении int *p = new int[n]; хоть нулю. n нужна только для того, чтобы компилятор корректно выделил память под массив из n элементов, так чтобы они все были рядом, шли непрерывно друг за другом. А указатель p осуществляет навигацию по памяти. При объявлении int *p = new int[n]; указатель p инициализируется значением адреса ячейки массива с 0 индексом, а может обслуживать не только массив, но и выходить за его пределы и мусорить в памяти или читать память, не относящуюся к массиву.
1
3 / 3 / 0
Регистрация: 28.11.2018
Сообщений: 242
07.02.2019, 03:17  [ТС]
SomniPhobia, это почему так получается? Что за 777u - что за "u"???

Добавлено через 1 минуту
SomniPhobia, та это всё я знаю, хорошо понимаю. Просто тот же вопрос, вернее люди выше разъяснили - спасибо огромное - но всё же как-то сложновато. Массив вроде создается, но вроде бы и нет...Нужно еще повтыкать, подумать.
0
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
07.02.2019, 08:37
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Массив вроде создается, но вроде бы и нет
Ты запросил у ОС память, тебе дали, а вот сколько дали, это на усмотрение ОСи, поэтому тебе выше и написали, что поведение будет Неопределенно!

Добавлено через 1 минуту
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
что за "u"???
unsigned - положительное число
1
 Аватар для SomniPhobia
602 / 439 / 137
Регистрация: 22.11.2017
Сообщений: 1,408
07.02.2019, 10:02
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
Массив вроде создается, но вроде бы и нет...Нужно еще повтыкать, подумать.
Массив из 0 элементов создаётся в любом случае. Память выделяется, но она выделяется не под 0 элементов. У меня при создании массива 0 длины создаётся массив на 1 элемент (зарезервировано памяти под 1 элемент), но я мало раз запускал, может разное кол-во быть.
Таким образом, если ты запрашиваешь массив на 0 элементов, то он создаётся как минимум на 1 элемент.

Добавлено через 5 минут
Цитата Сообщение от MJ_PRUTYG Посмотреть сообщение
это почему так получается
При резервации памяти, при создании массива, перед этим участком памяти создаётся метка, в которой на -4 позиции прописывается объём памяти, выделенный под этот массив. Там также всякие разметки стоят до и после выделенного под массив участка памяти. До - много всяких ячеек inf о массиве, после одна метка завершения выделенного участка.
Оказывается, при передачи массива в стороннюю функцию, можно не передавать размер, а передать только указатель. Затем с помощью функции _msize(a) (она берёт значение с позиции -4), где a - указатель на 0 элемент массива, можно узнать сколько памяти занимает массив. С помощью функции sizeof(int) можно узнать сколько занимает в памяти 1 элемент типа int. Чтобы найти кол-во элементов в массиве нужно общий объём выделенной памяти разделить на объём, занимаемый одним элементом.
auto size = _msize(a) / sizeof(int);
2
 Аватар для COKPOWEHEU
4082 / 2680 / 432
Регистрация: 09.09.2017
Сообщений: 11,900
07.02.2019, 13:00
SomniPhobia, все это зависит от компилятора. В одном может быть так, в другом - по-другому. Например, при выделении памяти на 0 элементов может выдаваться целая страница памяти, или указатель в запрещенную для доступа область. Метаинформация о выделенной памяти может храниться в специальной структуре не привязанной к собственно данным. Подобные подробности стандартом не регламентируются и полагаться на них нельзя.
1
 Аватар для SomniPhobia
602 / 439 / 137
Регистрация: 22.11.2017
Сообщений: 1,408
07.02.2019, 13:05
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
все это зависит от компилятора
Я заметил, что в ряде случаев ситуации разрешаются одним компилятором так, другим иначе. Почему так в C++?
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.02.2019, 13:08
SomniPhobia, потому что неопределённое поведение.
1
 Аватар для COKPOWEHEU
4082 / 2680 / 432
Регистрация: 09.09.2017
Сообщений: 11,900
07.02.2019, 15:49
Цитата Сообщение от SomniPhobia Посмотреть сообщение
Я заметил, что в ряде случаев ситуации разрешаются одним компилятором так, другим иначе. Почему так в C++?
Это сделано из соображений оптимизации и переносимости. Язык Си (а следом и С++) задумывался как высокоуровневый ассемблер. То есть он должен уметь выжимать из железа все его возможности и минимально ограничивать как программиста, так и разработчика компилятора. Отсюда и неопределенный размер основных типов данных, и куча неопределенных поведений, и многое другое.
Если программист разумный (а язык Си это почему-то предполагает верным... излишне оптимистично), то он следует стандарту языка, а раз так, то все не описанное в стандарте отдается на откуп разработчикам компилятора, чтобы получаемый код оказался оптимальным. Например, в стандарте сказано, что переполнение знаковой переменной неопределено -> программист так делать не будет -> переполнение будет обрабатываться в соответствии с архитектурой процессора. В некоторых оно приводит к "закольцовыванию" значений, в других - к остановке на максимуме, в третьих - к исключению.
Второй вывод, который из этого следует: программист может воспользоваться неопределенным поведением если это приведет к существенному выигрышу. Но только при условии что он пишет строго под один процессор и под один компилятор, то есть если он точно знает что делает. И знает, что при портировании на другие процессоры и компиляторы возникнут проблемы.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.02.2019, 15:49
Помогаю со студенческими работами здесь

Почему это называется динамический массив
SetLength(massiv,10) Последняя цифра выделяет память для n элементов (в примере n=10). Почему это называется динамический массив, если...

Почему двумерный динамический массив не запускается?
#include &lt;iostream&gt; #include &lt;cstdlib&gt; #include &lt;ctime&gt; using namespace std; int main() { int xstr; int ycol; ...

Динамический массив of variant, почему ошибка?
ребята привет,объясни пожалуйста почему так нельзя делать function myfyn(b:byte):variant; begin if b=5 then result:=true; end; ...

Почему не хочет брать динамический массив?
{$reference System.Windows.Forms.dll} {$reference System.Drawing.dll} uses System.Windows.Forms; var f: Form; lst1:...

Почему ДВССЫЛ на простой именованный диапазон работает, а на динамический именованный не работает?
Т.е. если создать список, который будет получать данные из именованного диапазона с фиксированным размером диапазона, то ДВССЫЛ вернёт...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru