Это довольно надуманная проблема, я признаю, но вот она.
Предположим, у вас есть файл с символом >
в имени. Это возможно в большинстве систем Unix Насколько мне известно:
$ touch 'weird>name'
$ ls -l
-rw-r--r-- 1 user user 0 28 Mag 11:05 weird>name
Теперь предположим, что этот файл содержит код C/C++, и вы хотите включить его в качестве заголовка:
#include <weird>name>
int main() {
return weird_function();
}
Clang выдает следующую ошибку:
test.cpp:1:10: fatal error: 'weird' file not found
#include <weird>name>
Конечно, так как препроцессор разбирает директиву до первого >
и ищет weird
файл. Но мне интересно, существует ли какой-то механизм экранирования, позволяющий мне включить правильный файл.
Итак, в C и/или C++ есть ли способ включить заголовочный файл, в имени которого есть символ >
?
Редактировать: Многие мне предлагали, почему бы не использовать #include "weird>name"
. Я признаю, что мой разум ускользнул от синтаксиса кавычек при написании вопроса, но он остается в силе, потому что два синтаксиса могут потребовать от компилятора поиска по разным путям (по крайней мере, теоретически). Итак, есть ли какой-либо механизм экранирования, позволяющий мне включать weird>name
с использованием синтаксиса #include <>
?
Как насчет того, чтобы добавить файл как #include "weird>name"
?
Да, но это может искать по разным путям. Я уточню.
На практике он может искать по одному дополнительному пути, что может быть проблемой только в том случае, если у вас есть файлы с именем weird>name
в нескольких местах. Если это правда, вам нужно разобраться с именами файлов и перестать заниматься глупостями :-P Правильный ответ должен быть "какая разница? просто не делайте этого"
"но у них разные пути поиска" - да, '<>': «Целью этого синтаксиса является поиск файлов, находящихся под контролем реализации»., поэтому вам никогда не придется об этом беспокоиться. Если вы включаете пользовательские файлы с помощью «<>», вы делаете это неправильно.
Используя #include "..."
, если препроцессор не может найти заголовочный файл там, где он ищет, он попытается #include <...>
затем, возможно, в другом пространстве поиска.
@pmg Разве это не то, что сказали Shravan40, Джонатан Уэйкли и ОП?
@Sneftel: то же самое; это немного более заметно само по себе, даже если в комментарии.
Если вы не можете переименовать файл, создайте символическую ссылку на файл с более подходящим именем.
Аналогичная проблема может возникнуть, если имя файла содержит символы, которых нет в исходном наборе символов (который определяется реализацией). например ?.ч
@eerorika Я не понимаю твоей точки зрения... какое это имеет отношение к намерениям?
Теперь ясно, что продолжение должно включать действительно "странное> имя!
So, in C and/or C++, is there a way to include an header file which has the > character in its name?
Да:
#include "weird>name"
So is there any escaping mechanism to let me include
weird>name
using the#include <>
syntax?
Нет. Символы между <
и >
должны быть «любыми членами исходного набора символов, кроме новой строки и >
» ([lex.заголовок]). Редактирование Любая экранированная форма : реализациям разрешено поддерживать управляющие последовательности, определенные реализацией (см. [lex.header] p2 и его сноску).>
по-прежнему будет способом представления символа >
, что недопустимо.
Форма #include " q-char-sequence "
делает позволяет отображать символ >
, даже если он может быть повторно обработан как #include <...>
, если поиск как "..."
не удался ([cpp.include] p3).
Препроцессор также допускает другую форму ([cpp.include] p4](http://eel.is/c++draft/cpp.include#4)), но ее эффект определяется реализацией, а реализации, которые я пробовал, не позволяют объединять weird
, >
и name
в один токен препроцессора, который затем может быть включенным
Далее: как я могу включить заголовочный файл, который содержит "
в своем имени?
Я признаю, что мой разум ускользнул от синтаксиса "file"
, но вопрос остается актуальным, хотя и немного менее интересным, потому что <>
и ""
могут искать по разным путям.
@gigabytes Это действительно единственное решение из-за того, как определена грамматика языка! nongnu.org/hcb/#имя-заголовка
@gigabytes — обычно <>
означает, что препроцессор ищет в местах, определенных системой (т. е. специфичных для компилятора), а ""
означает, что он ищет в местах, определенных пользователем (т. е. которые вы можете указать). Ни один уважающий себя компилятор не будет иметь заголовочный файл с таким именем, как вы описываете, поэтому вы не будете использовать форму <>
.
С параметрами компилятора вы можете установить оба пути.
Но это, очевидно, не уважающий себя вопрос, поэтому вы можете предположить, что мы не используем уважающий себя компилятор: P
@gigabytes «С параметрами компилятора вы можете установить оба пути». Да, но не отдельно. Обычно все пути, которые ищутся для <...>
, также ищутся для "..."
, если первый поиск не удался. Опция GCC -I-
позволяет вам это изменить, но она устарела, не соответствует требованиям, не работает и не поддерживается другими компиляторами.
Означает ли это, что файл с именем weird>name"
никогда не может быть включен?
Правило состоит в том, что h-char-последовательность не должно быть содержать>
(C 2018 6.4.7 1), а не то, что символы в нем не могут быть представлять>
. Если бы реализация C определила некоторую последовательность символов в h-char-последовательность, которая представляла бы >
в пути к файловой системе, это не нарушило бы стандарт C. Например, #include <weird%3ename>
разрешено стандартом C, где %3e
представляет >
.
Я не уверен, что вторая часть правильная. Любая попытка сбежать >
на самом деле не будет >
персонажем. Тем не менее, препроцессор не обязан распознавать какие-либо управляющие последовательности.
Да, я изменил этот бит сейчас.
@Kane, посмотрите редактирование ответа - его никогда нельзя включить надежно, но некоторые реализации могут предоставить способ сделать это.
Спросите у автора вашего компилятора.
Стандарты C и C++ предоставляют большую свободу действий при интерпретации директив #include
. Нет требования, чтобы #include <foo.h>
вызывал включение файла с именем «foo.h». Например, компилятор может выбрать ROT13 для всех имен исходных файлов, если он хочет. А для небуквенно-цифровых символов реализация может идентифицировать и переназначать определенные последовательности символов. Поэтому, если бы была платформа, где >
регулярно появлялась в именах файлов, вполне вероятно, что компилятор для этой платформы указал бы, что, скажем, \g
или что-то было бы переназначено на >
. Но стандарт не предписывает конкретную кодировку.
Кстати, реализация могла бы также просто разрешить #include <weird>name>
. Поскольку это не соответствует языковым стандартам, реализация может определять его значение как расширение.
Попробуйте синтаксис ниже:
#include "weird>name"
Шаг 1: переименуйте файл. Шаг 2: готово.