it-swarm.com.ru

Допустим ли обратный слеш в директивах C и C++ #include?

Обычно используются два разделителя пути: прямая косая черта Unix и обратная косая черта DOS. Покойся с миром, Классический Mac Colon. Если они используются в директиве #include, равны ли они правилам стандартов C++ 11, C++ 03 и C99?

38
Potatoswatter

C99 говорит (§6.4.7/3):

Если символы ', \, ", // или/* встречаются в последовательности между разделителями <и>, поведение не определено. Аналогично, если символы', \, // или/* встречаются в последовательности между «разделителями» поведение не определено.

(сноска. Таким образом, последовательности символов, которые напоминают escape-последовательности, вызывают неопределенное поведение.)

C++ 03 говорит (§2.8/2):

Если любой из символов или \, или любой из последовательностей символов/* или // появляется в q-char-последовательности или h-char-последовательности, или символ "появляется в h-char-последовательности, поведение не определено.

(сноска. Таким образом, последовательности символов, которые напоминают escape-последовательности, вызывают неопределенное поведение.)

C++ 11 говорит (§2.9/2):

Появление символов или\или любой последовательности символов/* или // в последовательности q-char или h-char условно поддерживается семантикой, определяемой реализацией, как и появление символ "в h-char-последовательности.

(сноска. Таким образом, последовательность символов, напоминающая escape-последовательность, может привести к ошибке, интерпретироваться как символ, соответствующий escape-последовательности, или иметь совершенно другое значение, в зависимости от реализации.)

Таким образом, хотя любой компилятор может предпочесть поддержку обратной косой черты в пути #include, маловероятно, что какой-либо поставщик компилятора не поддержит прямую косую черту, и обратная косая черта, вероятно, приведет к отключению некоторых реализаций благодаря формированию escape-кодов. (Редактировать: очевидно, MSVC ранее требовал обратной косой черты. Возможно, другие на платформах, производных от DOS, были похожи. Хммм… что я могу сказать.)

C++ 11 кажется ослабляет правила, но «условно поддерживаемая» не намного лучше, чем «вызывает неопределенное поведение». Это изменение больше отражает существование некоторых популярных компиляторов, чем описание переносимого стандарта.

Конечно, ни в одном из этих стандартов ничего не говорится о том, что существует такая вещь, как пути. Там есть файловые системы без путей вообще! Однако многие библиотеки предполагают имена путей, в том числе POSIX и Boost, поэтому разумно хотеть использовать переносимый способ обращения к файлам в подкаталогах.

47
Potatoswatter

Косая черта - правильный путь; прекомпилятор сделает все возможное на каждой платформе, чтобы получить правильный файл.

7
trojanfoe

Это зависит от того, что вы подразумеваете под «приемлемым».

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

Если вы пишете C99, C++ 03 или C1x, обратная косая черта не определена, в то время как косая черта допустима, поэтому в этом смысле обратная косая черта недопустима.

Но это не имеет значения для большинства людей. Если вы пишете C++ 1x, где обратная косая черта поддерживается условно, и платформа, для которой вы кодируете, поддерживает их, они приемлемы. И если вы пишете «расширенный диалект» C99/C++ 03/C1x, который определяет обратную косую черту, то же самое. И, что более важно, в любом случае это понятие «приемлемый» в большинстве случаев совершенно бессмысленно. Ни один из стандартов C/C++ не определяет, что означает косая черта (или что означает обратная косая черта, когда они условно поддерживаются). Имена заголовков сопоставляются с исходными файлами способом, определяемым реализацией, точка. Если у вас есть иерархия файлов, и вы спрашиваете, использовать ли обратную косую черту или косую черту, чтобы ссылаться на них в директивах #include, ответ таков: ни один из них не является переносимым. Если вы хотите написать действительно переносимый код, вы не можете использовать иерархии заголовочных файлов - фактически, возможно, вам лучше всего написать все в одном исходном файле, а не #include ничего, кроме стандартных заголовков.

Однако в реальном мире люди часто хотят быть «достаточно портативными», а не «строго портативными». Стандарт POSIX предписывает, что означает косая черта, и даже за пределами POSIX большинство современных платформ, включая Win32 (и Win64), кросс-компиляторы для встраиваемых и мобильных платформ, таких как Symbian и т.д., Обрабатывают косые черты в POSIX, по крайней мере, настолько, насколько это возможно. C/C++ #include директивы. Любая платформа, которая не имеет, вероятно, не будет для вас способа вставить на нее свое исходное дерево, обработать ваш make-файл и т.д. И т.д., Поэтому директивы #include будут меньше всего беспокоить вас. Если это то, что вас волнует, то косые черты допустимы, а обратные косые черты - нет.

5
abarnert

Blackslash - неопределенное поведение, и даже с косой чертой вы должны быть осторожны. Стандарт C99 гласит:

Если символы ', \, ", // или /* Встречаются в последовательности между разделителями < И>, поведение будет Undefined. Аналогично, если Characters', \, // или/* встречаются в последовательности между "разделителями, поведение не определено.

5
Jens Gustedt

Всегда используйте косую черту - они работают на большем количестве платформ. Обратная косая черта технически вызывает неопределенное поведение в C++ 03 (2.8/2 в стандарте).

1
Alan Stokes

Стандарт говорит для #include, что это:

ищет последовательность мест, определенных реализацией, для заголовок, идентифицируемый однозначно указанной последовательностью между разделители, и вызывает замену этой директивы на все содержимое заголовка. Как указаны места или заголовок идентифицировано, определяется реализацией.

Обратите внимание на последнее предложение.

0
Neil Butterworth