, который я считаю, это также доказательства того, что аргументы могут иметь пробелы вокруг него
Нет, на самом деле это только укрепляет положение эталона, что каждый макрос аргумент является последовательность предварительной обработки лексем (C2011, 6.10.3/11). Пробелы в исходном файле разделяют токены предварительной обработки; пробелы пробелов не являются самими препроцессорными жетонами.
Раздел стандартного номера, который вы цитируете, потенциально запутан, потому что он смешивает уровни - последовательность символов исходного файла, к которому относится пробел, и последовательность токенов предварительной обработки, возникающая из-за цельной токенизации исходной последовательности. Действительно, стробирование чувствительно к тому, что соседние маркеры разделены пробелом в исходной последовательности символов, но детали любого такого пробела вообще не имеют значения - при строкообразовании смежные маркеры, разделенные пробелами, разделяются одним пространством символ в результирующей строке.
Это не означает, что токен предварительной обработки может начинаться или заканчиваться пробелом. Это невозможно; подробные сведения см. в разделе 6.4 стандарта.То, как данная реализация удовлетворяет спецификациям для строкования, обязательно является специфичной для реализации, но один из способов реализации этой реализации мог бы включать в себя сохранение булевых флагов для каждого токена предварительной обработки, описывающего, предшествует ли этот токен и/или следует в исходной последовательности по пробелам. Такие данные не имеют ничего общего с интерпретацией того, что стандарт указывает на результат, однако, ни для оператора строковой обработки, ни для оператора вставки меток.
для аргументов, которые будут объединены оператором ##, что должен делать компилятор относительно его пространств?
К тому времени ##
оператора (или оператора #
) входит в игру, компилятор уже сделал все, что когда-либо будет (непосредственно) делать с пробельных символов появляется в исходном файле, рассматривая их в токенизации из источник в токены предварительной обработки. Макро-аргументы - это последовательности токенов предварительной обработки, и только в той степени, в которой эти токены могут быть строковыми или символьными литералами или именами заголовков, могут содержать пробелы. Кроме того, стандарт определяет:
Если в списке замещения функции, как макро, параметр непосредственно предшествуют или следует ##
предварительной обработки маркера, параметр заменяется соответствующим аргумент предварительной обработки маркера последовательность [...]
(C2011, 6.10.3.3/2; курсив добавлен)
Еще раз, пробельные пробеги не Preprocessing маркеры. Расширение макроса и операторы #
и ##
имеют дело с уровнями последовательностей токенов предварительной обработки и работают с ними. Пробелы представлены на этом уровне только внутри маркеров. Пробел из исходного файла, который не является внутренним для токена предварительной обработки, представлен только косвенно и неопределенно в последовательности токенов предварительной обработки.
Я вижу. Большое вам спасибо за ваш ответ. Но мне интересно, если компилятор не включает пробел в последовательности токенов предварительной обработки аргумента, как он будет выполнять строчение? Я имею в виду, как он должен знать, куда помещать пробел между соседними токенами предварительной обработки, а где нет. Думаю, это не только записывает последовательность токенов, но и информацию о белых пробелах? Что говорит об этом стандарт? –
@WuZhenwei, вы правы, что стробирование не вставляет пробел между токенами предварительной обработки, где в исходной последовательности символов нет. Поскольку препроцессору не важно, сколько пробелов есть или какие конкретные символы пробелов находятся в таких местах, он может отслеживать по принципу токена-маркера, должны ли перед знаками предшествовать и/или сопровождаться пробелами. Это деталь реализации. Я уточню свой ответ, чтобы уточнить. –