Объясните как это работает
Не понимаю почему именно такие результаты выводит. Простой интерес, практического применения не вижу
int main()
{
cout << 4 + "0" << "\n";
cout << 8 + "0" << "\n";
cout << 12 + "0" << "\n";
cout << 12 + "0" << "\n";
cout << 16 + "0" << "\n";
cout << "h"- "0" << "\n";
cout << "e" - "0" << "\n";
cout << "l" - "0" << "\n";
cout << "l" - "0" << "\n";
cout << "o" - "0" << "\n";
cout << "g" - "0" << "\n";
cout << "l" - "0" << "\n";
}
Ответы (3 шт):
Вы столкнулись с неопределённым поведением. То, что вы видите, может меняться от компилятора к компилятору, и от компьютера к компьютеру.
В своём коде вы складываете и вычитаете не строки, а указатели на эти строки:
4 + "0"; // const char*
"h" - "0" // ptrdiff_t
В первом случае вы получаете указатель на некоторый участок памяти. И пробуете вывести строку, начинающуюся с этого участка. Компьютер будет пытаться представить байты этой памяти как символы в некоторой кодировке до тех пор, пока не встретит нуль-терминатор.
Скорее всего, ваш компилятор поместил строки "0", "h", "e", "l", "o", "g" достаточно близко в памяти. Строка "0" находится раньше всех. И когда вы прибавляете к её указателю небольшое число, вы попадаете на строку "h".
Обратите внимание, что я говорю именно строки, не символы. Потому что "h" содержит 2 символа — 'h' и '\0'. Последний как раз и представляет собой нуль-терминатор. И если вы попадаете указателем в 'h', то компьютер заканчивает печать на следующем же символе.
Во втором случае результат выражения неявно приводится к числу. И вы просто видите разницу между указателями.
Вы складываете и вычитаете указатели.
Вычитание работает правильно только если указатели указывают на элементы одного и того же массива (&a[i] - &a[j] == i - j), иначе вы получаете неопределенное поведение. В вашем примере они указывают на первые элементы разных массивов, поэтому поведение не определено.
А сложение работает так: &a[i] + x == &a[i + x]. Если индекс получившегося элемента выходит за границы массива, опять же происходит неопределенное поведение, как в вашем случае.
Почему вы видите именно такие числа? Потому что компилятор поместил все ваши строки рядом в памяти. Грубо говоря, там что-то типа массива const char x[] = {'0','\0','h','\0','e', ...}; Конкретный порядок строк стандартом не гарантируется, как и то, что они будут в памяти рядом, и то, будут ли повторяющиеся строки иметь разные адреса.
Здесь "h" превращается в &x[2], и т.п. Дальше подставляете результат в формулы выше. Можете поэкспериментировать с порядком элементов в массиве, чтобы получить такие же числа, как у вас сейчас.
Стало интересно повторить. Итак, на VC++ это достигается, например, так:
const char * m[] = {"0","h","e","l","o"};
int main()
{
cout << 4 + "0" << "\n";
cout << 8 + "0" << "\n";
cout << 12 + "0" << "\n";
cout << 12 + "0" << "\n";
cout << 16 + "0" << "\n";
}
Но! обязательно должна быть включена (вернее, не отключена) опция /GF (включить объединение строк только для чтения). Стоит скомпилировать как /GF-, как все "0" становятся разными и всё становится очень грустно...
