Почему комментарий не может быть заменен пробелами в Visual C ++ 2008 - PullRequest
2 голосов
/ 17 декабря 2010

В Visual Studio 2008 (без SP1) я могу скомпилировать и запустить этот код

// vcconsole.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#define NOERROR
#ifdef   /* 

   */  NOERROR
void pr() {
 printf("hello world..\n");
} 
#endif

int _tmain(int argc, _TCHAR* argv[])
{
 pr();
 return 0;
}

Но если я вручную заменю комментарий блока пробелами:

// vcconsole.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#define NOERROR
#ifdef      

       NOERROR
void pr() {
 printf("hello world..\n");
} 
#endif

int _tmain(int argc, _TCHAR* argv[])
{
 pr();
 return 0;
}

не скомпилируется с ошибкой:

1>------ Build started: Project: vcconsole, Configuration: Debug Win32 ------
1>Compiling...
1>vcconsole.cpp
1>c:\x64\winproj\vcconsole\vcconsole.cpp(6) : fatal error C1016: #if[n]def expected an identifier
1>Build log was saved at "file://c:\x64\winproj\vcconsole\Debug\BuildLog.htm"
1>vcconsole - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Почему 2 не эквивалентны?

Это касается меня, потому что я использую инструмент для удаления всех комментариев из моего исходного кода на c ++ (мне нужно сделать это по другим причинам) перед их компиляцией. Если 2 не эквивалентны, мой инструмент может не работать.

Ответы [ 4 ]

3 голосов
/ 17 декабря 2010

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

Обратите внимание, что в [lex.parses] 2.1.1.3 «Каждый комментарий заменяется одним пробелом».до 2.1.1.4 «Выполняются директивы препроцессора и расширяются вызовы макросов».

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

Итак, мое предварительное объяснение несоответствующего поведения переключателя предварительной обработки Microsoft: Visual C ++ делает что-то не-Стандарт в сохранении новых строк в комментариях (возможно, для отслеживания номеров строк), поэтому он должен встроить некоторое отслеживание и допуск для последующих многострочных директив предварительной обработки, сохраняя их работоспособность./ P и / E выводят нестандартные многострочные директивы, но теряют метаданные отслеживания, которые делают его компилируемым.

2 голосов
/ 17 декабря 2010

из стандарта, раздел 16.1

Единственные пробельные символы который должен появиться между токенами предварительной обработки в пределах
директива предварительной обработки (от просто после введения # препроцессинга маркер до завершающий символ новой строки) пробел и горизонтальная вкладка (в том числе пробелы, которые заменили комментарии или, возможно, другие пробелы символы в фазе перевода 3).

g ++ также (правильно) не может скомпилировать код.

2 голосов
/ 17 декабря 2010

Замена на пробел приведет к:

#ifdef      NOERROR

Однако вы заменили пробелами и символами новой строки .Директивы препроцессора заканчиваются символами новой строки так же, как операторы C ++ заканчиваются точкой с запятой.

1 голос
/ 17 декабря 2010

Первый работает, потому что комментарий является комментарием и, следовательно, игнорируется препроцессором и компилятором. Второй не работает, потому что макросы не могут занимать несколько строк, если вы не поставите \ в качестве последнего символа каждой строки.

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

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