Почему строковый оператор принимается только как макрос? - PullRequest
4 голосов
/ 11 апреля 2019

Я пытался использовать оператор # в своем коде:

#include <stdio.h>

int main(void)
{
    printf("hello %s !!! n", #world);
    return 0;
}

Этот код, скомпилированный с gcc, выдает следующую ошибку:

str.c: In function ‘main’:
str.c:5:27: error: stray ‘#’ in program
  printf("hello %s !!! n", #world);

Но когда я определяю макрос, который использует этот оператор, код компилируется:

#include <stdio.h>

#define STRINGIFY(x) #x

int main(void)
{
    printf("hello %s \n", STRINGIFY(world));
    return 0;
}

Об этом сообщает препроцессор? Если так, то почему?

Ответы [ 2 ]

3 голосов
/ 11 апреля 2019

Поскольку #parameter является частью расширения macro . Все это делается препроцессором еще до того, как компилятор увидит код. И этот токен применяется только к макропараметрам. Рассмотрим следующий макрос:

#define STR(x) #x

Str(Hello) - это "Hello"

Но если мы напишем #word в коде, препроцессор не увидит это как часть макроса, и word не является параметром макроса. Таким образом, препроцессор игнорирует это. Компилятор видит одно и то же слово и ничего не знает, что с ним делать. Таким образом, он сообщает об ошибке. Рассмотрим следующий текст, разработанный препроцессором.

#define STR(x) #x
const char * str=STR(Hello);
const char * buggy_str=#Hello;

Результат будет:

const char * str="Hello";
const char * buggy_str=#Hello;

Компилятор C видит первую строку, и он в порядке. Но когда он видит вторую строку, он ничего не знает о токене # и, таким образом, сообщает об ошибке.

2 голосов
/ 11 апреля 2019

Символ # разрешен только в программе на C внутри:

  1. Комментарии
  2. Строковые и символьные литералы
  3. Директивы препроцессора

Это определяется стандартом C.

В вашей программе он находится вне любого из этих контекстов, поэтому он помечается как "отклоненный", и программа отклоняется.

Стандарт C не определяет, какие фазы перевода отвечают за диагностику. В любом случае, они являются только концептуальными фазами и могут быть или не быть идентифицируемыми в реальном компиляторе. Таким образом, вопрос о том, была ли ошибка передана во время предварительной обработки, не вполне определен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...