Краткий ответ: Это Неопределенное поведение
Длинный ответ: В C ++ выделение массива размером 0
даст действительный указатель на массив без элементов.
Из стандарта (взято из этот ответ ):
Из 5.3.4 / 7
Когда значение выражения в директиве new-new объявлено равным нулю, вызывается функция выделения для выделения массива без элементов.
От 3.7.3.1/2
Эффект разыменования указателя, возвращаемого как запрос нулевого размера, не определен.
(Акцент мой)
Это означает, что нет способа правильно прочитать из (или записать в) указатель, возвращенный из запроса new T[0]
.
И strlen
, и printf
для форматирования строки "%s
" определены для работы со строками символов, которые заканчиваются специальным символом NUL
. Они требуют чтения последовательности символов из предоставленного указателя, чтобы попытаться найти этот NUL
символ для правильной работы (что приводит к UB, поскольку для этого требуется разыменование указателя). Это поведение определено в стандарте C, поскольку стандарт C ++ делегирует определения большинства типов / функций библиотеки C обратно стандарту C.
printf
доступ для %s
определяется следующим образом:
Из стандарта C11 § 7.21.6.1 / 6
Если модификатор длины l отсутствует, аргумент должен быть указателем на начальный элемент массива символьного типа.
Символы из массива записываются до (но не включая) завершающего нулевого символа. Если указана точность, записывается не более этого количества байтов. Если точность не указана или превышает размер массива, массив должен содержать нулевой символ.
Для этого требуется доступ к массиву (который будет UB, поскольку указатель недопустим для разыменования)
Бонус
Ваш пример кода фактически вводит UB во второй строке из-за использования strlen
, по тем же причинам, что и выше.
strlen
определено для выполнения следующих действий:
Из стандарта C11 §7.24.6.3 / 3: Функция strlen
Returns
Функция strlen возвращает количество символов, предшествующих завершающему нулевому символу.
Который является UB по той же причине, что и printf
.