Почему два строковых литерала, разделенных пробелом, табуляцией или "\ n", могут быть скомпилированы без ошибок?

int main()
{
   char * a = "aaaa"  "bbbb";
} 

"aaaa" - это символ * "bbbb" - это символ *

Не существует специального правила конкатенации для обработки двух строковых литералов. И, очевидно, следующий код выдает ошибку во время компиляции:

#include <iostream>
int main()
{
   char * a = "aaaa";
   char * b = "bbbb";
   std::cout << a b;
}

Общая ли эта конкатенация для всех компиляторов? Где нулевое окончание "аааа"? "Aaaabbbb" - это непрерывный блок ОЗУ?

4
Ivan Ustinov 5 Сен 2016 в 12:04

4 ответа

В этом заявлении

char * a = "aaaa"  "bbbb";

Компилятор на каком-то этапе компиляции перед синтаксическим анализом рассматривает смежные строковые литералы как один литерал.

Таким образом, для компилятора приведенный выше оператор эквивалентен

char * a = "aaaabbbb";

То есть компилятор хранит только один строковый литерал "aaaabbbb"

5
Vlad from Moscow 5 Сен 2016 в 09:07

Смежные строковые литералы объединяются в соответствии с правилами стандарта C (и C ++). Но для смежных идентификаторов (т. Е. Переменных a и b) такого правила не существует.

Чтобы процитировать, C ++ 14 (проект N3797), § 2.14.5:

На этапе перевода 6 (2.2) смежные строковые литералы объединяются. Если оба строковых литерала имеют одинаковый префикс кодирования, результирующий конкатенированный строковый литерал имеет этот префикс кодирования. Если один строковый литерал не имеет префикса кодирования, он рассматривается как строковый литерал того же префикса кодирования, что и другой операнд. Если токен строкового литерала UTF-8 соседствует с токеном широкого строкового литерала, программа имеет неправильный формат. Любые другие конкатенации условно поддерживаются с поведением, определяемым реализацией.

4
P.P 5 Сен 2016 в 09:07

Строковые литералы, помещенные бок о бок, объединяются на этапе перевода 6 (после препроцессора). То есть "Hello," " world!" возвращает (единственную) строку "Hello, world!". Если две строки имеют одинаковый префикс кодирования (или ни одна из них не имеет его), результирующая строка будет иметь один и тот же префикс кодирования (или без префикса).

(исходный код)

2
Michael 5 Сен 2016 в 09:07

В C и C ++ смежные строковые литералы компилируются как один строковый литерал. Например это:

"Some text..." "and more text"

Эквивалентно:

"Some text...and more text"

Это по историческим причинам:

Исходный язык C был разработан в 1969-1972 годах, когда в вычислениях все еще преобладали перфокарты с 80 столбцами. Его разработчики использовали 80 колонных устройств, таких как телетайп ASR-33. Эти устройства не переносили текст автоматически, поэтому было реальным стимулом хранить исходный код в пределах 80 столбцов. Для этого у Fortran и Cobol были явные механизмы продолжения, прежде чем они наконец перешли на свободный формат.

Для Денниса Ричи (я полагаю) было блестящим ходом осознать, что в грамматике нет двусмысленности и что длинные строки ASCII можно уместить в 80 столбцов, просто заставив компилятор объединить смежные буквальные строки. Бесчисленное количество программистов на C были благодарны за эту небольшую возможность.

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

Аналогичный вопрос здесь.

3
Community 20 Июн 2020 в 09:12