2016-09-05 8 views
4

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

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

«аааа» является символ * «BBBB» является символом *

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

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

Является ли это конкатенация общей для всех компиляторов? Где нулевое прекращение «aaaa»? Является ли «aaaabbbb» непрерывным блоком ОЗУ?

+5

Это массивы символов, а не указатели –

ответ

9

Если вы видите, например, this translation phase reference в фазе 6:

Смежные строковые литералы объединены.

И вот что здесь происходит. У вас есть два смежных строковых литерала, и они объединены в один строковый литерал.

Это стандартное поведение.

Он работает только для строковых литералов, а не из двух переменных указателя, как вы заметили.

2

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

(source)

5

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

char * a = "aaaa" "bbbb"; 

компилятор в каком-то шаге компиляции до синтаксического анализа рассматриваются смежные строковые литералы в качестве одного буквального.

Так что для компилятора приведенное выше утверждение эквивалентно

char * a = "aaaabbbb"; 

, который компилятор хранит только одну строку буквального "aaaabbbb"

4

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

Процитирует, C++ 14 (N3797 проекта), § 2.14.5:

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

3

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

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

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

"Some text...and more text" 

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

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

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

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

Similar question here.

+1

Откуда у вас такая цитата? – anatolyg

+0

@anatolyg Добавлены ссылки –