#line - цели? - PullRequest
       3

#line - цели?

7 голосов
/ 07 августа 2010

К сожалению, сегодня я занимался небольшой археологией кода (в то же время реорганизуя какой-то старый опасный код) и нашел немного окаменелости, подобной этой:

# line 7 "foo.y"

Я был совершенно изумлен, обнаружив там такое архаичное сокровище,Я прочитал об этом на веб-сайте для программирования на C.Однако это не объясняло, ПОЧЕМУ кто-то хотел бы использовать это.Поэтому я был оставлен наедине с собой, чтобы предположить, что программист вставил это исключительно для чистой радости лжи компилятору.

Примечание: (Имейте в виду, что ископаемое вещество фактически находилось в строке 3 файла cpp) (Ои файл действительно указывал на файл .y, который был почти идентичен этому файлу.

Кто-нибудь знает, зачем нужна такая директива? Или для чего ее можно использовать?

Ответы [ 5 ]

17 голосов
/ 07 августа 2010

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

Таким образом, когда вы получаете сообщение об ошибке:

a += xyz;
     ^ No such identifier 'xyz' on line 15 of foo.y

Вы можете посмотреть на строку 15 исходного файла, чтобы увидеть проблему.

В противном случае он говорит что-то смешное, например No such identifier 'xyz' on line 1723 of foo.c, и вам нужно вручную сопоставить эту строку в автоматически сгенерированном файле C с эквивалентом в вашем реальном файле. Поверьте мне, если вы не хотите быть глубоко вовлеченным во внутренние механизмы лексического и семантического анализа (или если вы хотите кровоизлияние в мозг), вы не хотите проходить через код, сгенерированный yacc (bison может генерировать более хороший код Я не знаю, но меня это не волнует, так как я пишу код более высокого уровня).

Имеет две формы согласно стандарту C99:

#line 12345
#line 12345 "foo.y"

Первый устанавливает только номер строки сообщения, второй также изменяет имя файла сообщения, поэтому вы можете получить ошибку в строке 27, равную foo.y вместо foo.c.


Что касается того, что "программист вставил это просто ради радости лжи компилятору", нет. Мы можем быть согнуты и искривлены, но мы обычно не злы :-) Эта строка была помещена туда yacc или bison сама, чтобы сделать вам одолжение.

5 голосов
/ 07 августа 2010

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

2 голосов
/ 07 августа 2010

У него более глубокая цель. Оригинальный препроцессор C был отдельной программой от компилятора. После слияния нескольких файлов .h в файл .c люди все еще хотели знать, что сообщение об ошибке исходит из строки 42 stdio.h или строки 17 из main.c. Без каких-либо средств связи у компилятора не было бы способа узнать, какой исходный файл изначально содержал строку кода, вызывающую ошибку.

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

Конечно, в этом случае вы смотрите на файл, который был написан инструментом (вероятно, с именем yacc или bison), который используется для создания анализаторов из описания их грамматики. Этот файл на самом деле не является исходным файлом. Он был создан из реального исходного текста.

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

2 голосов
/ 07 августа 2010

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

Я никогда не видел эту директиву, которую программист использовал вручную, и я не уверен, насколько это будет полезно.

1 голос
/ 07 августа 2010

Я использовал #line и #error для создания временного * .c-файла, который вы компилируете, и ваша IDE дает вам список ошибок, найденных каким-либо сторонним инструментом.

Например, я передал выходной файл из PC-LINT в скрипт perl, который преобразовал читаемые человеком ошибки в строки #line и #error. Затем скомпилировал этот вывод, и моя среда разработки позволяет мне проходить через каждую ошибку, используя F4. Намного быстрее, чем вручную открывать каждый файл и переходить к определенной строке.

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