Подтвердить что ты не робот

Как С++ интерпретирует cout с "+" в нем?

Я двигался вперед и назад с помощью Java/С++, поэтому я испортил свой вывод на консоль и случайно написал строки, например:

cout << "num" + numSamples << endl;
cout << "max" + maxSampleValue << endl;

Каждый из них дал мне кусочки других строк, которые у меня были в моей программе. Я осознаю свою ошибку сейчас, но что такое С++, интерпретирующий эти строки так, чтобы они выводили разные части разных строк в моей программе?

4b9b3361

Ответ 1

Для этого есть простая причина:

"num" и "max" являются строковыми литералами. Их тип const char *. Предполагая, что numSamples является целым числом, то, что вы делаете, является арифметикой указателя.

Вы в основном печатаете строку, которая указывает на "num" + numSamples bytes.

Если вы сделали cout << "num" + 1 << endl, это напечатает "um".

Вероятно, вы поняли это, но правильный способ сделать это: cout << "num" << numSamples << endl;

Кроме того, вы спросили:

Но что такое С++, интерпретирующий эти строки так, чтобы они выводили разные части разных строк в моей программе?

Как указано выше, "num" является строковым литералом. Обычно строковые литералы сидят в одном месте в двоичной программе: .rodata. Все остальные строковые литералы сидят в этом регионе, поэтому, когда вы продвигаете указатель на определенное количество байтов, вы, вероятно, укажете на некоторые другие строковые литералы, тем самым напечатав (часть) их.

Ответ 2

Это просто арифметика указателя. Например,

cout << "num" + 1 << endl;

будет печатать строку, смотрящую из ((address of)"num" + 1), т.е. "um".

Если добавляемое нами значение превышает длину строки, то мы имеем поведение undefined.

Ответ 3

Имейте в виду, что хотя iostreams перегружают <<>>) для ввода-вывода, они были первоначально определены как операторы смены битов. Когда компилятор разбирает выражение, он в основном видит "операнд, оператор, операнд", а затем проверяет, являются ли операнды типов, к которым этот оператор может быть применен.

В этом случае у нас есть строковый литерал и (по-видимому) какое-то целое число, и компилятор знает, как выполнять математику на них (после преобразования строкового литерала в указатель).

Однако с точки зрения компилятора это не сильно отличается от чего-то вроде:

int a, b=1, c=2, d = 3;

a = b << c + d;

Разница заключается в том, что с операндами типа int смысл довольно очевиден: он выполняет добавление и бит-сдвиг. С iostreams значение, связанное с << и >>, изменяется, но синтаксис, разрешенный для них в выражении, не изменяется.

Из точки зрения компилятора единственный вопрос заключается в том, являются ли операнды для + типов, для которых разрешен + - в этом случае у вас есть pointer to char + integer, поэтому это разрешено. Результатом является указатель на char, и он имеет перегрузку <<, которая берет левый операнд типа ostream и правый оператор типа pointer to char, поэтому выражение в целом отлично ( насколько это важно).

Ответ 4

"num" Тип char const [4]. Если numSamples является целым числом, тип "num" + numSamples имеет значение const char *. Таким образом, вы вызываете operator << cor std::cout, который перегружен для const char * и печатает строку, которая начинается с адреса addres ( "num" ) + numSamples в арифметике указателя.

Попробуйте следующее:

cout << "num" + std::to_string(numSamples) << endl;
cout << "max" + std::to_string(maxSampleValue) << endl;

std::to_string() вы можете найти в <string>

Ответ 5

если вы посмотрите operator_precedence, вы увидите, что + оценивается до <<, что оставляет это выражение оценивается перед передачей оператору <<:

"num" + numSamples

Теперь "num" будет static const char *, и я предполагаю, что numSamples является интегральным типом. Поскольку левая часть + является типом указателя и вы добавляете к ней эту арифметику указателя. Теперь cout получает указатель на место в памяти, которое numSamples или maxSamplueValue больше, чем местоположение "num" или "max". Скорее всего, все ваши статические строки были выстроены в один и тот же регион памяти, поэтому вы видели их, а не случайную бред.