__FILE__ В .h, что это решает в - PullRequest
13 голосов
/ 19 февраля 2011

Существует ли спецификация того, как макрос __FILE__ будет расширен, если он находится в .h?

Если я определю в foo.h

#define MYFILE __FILE__

И включить его в foo.c

#include "foo.h"

int main(){
  printf("%s",MYFILE);
  ....
}

Это вывод foo.h или foo.c? (Да, я понимаю, что это глупый пример)

Извините за то, что должен быть простой вопрос. Документация в Интернете кажется противоречивой. Для чего это стоит VS2008 возвращается как foo.c, что я и ожидал .... Я думаю. Я просто пытаюсь подтвердить, определено ли это поведение.

Ответы [ 5 ]

10 голосов
/ 19 февраля 2011

Совет, данный в Ян '* ответ , является «в целом правильным». То есть значение __FILE__ - это имя текущего исходного файла, когда используется макрос, а не когда макрос определен. Однако это не совсем правильно - и вот контрпример:

$ cat x.h
static void helper(void)
{
    printf("%s:%d helper\n", __FILE__, __LINE__);
}
$ cat x.c
#include <stdio.h>
#include "x.h"

int main(void)
{
    helper();
    printf("%s:%d\n", __FILE__, __LINE__);
    return 0;
}

$ make x
cc -Wall -Wextra -std=c99 -g x.c -o x
$ ./x
x.h:3 helper
x.c:7
$

Это надуманный пример; в C вы очень редко помещаете реальный код в заголовок, как я делал здесь - если только вы не используете inline функции. Но выходные данные показывают, что существуют обстоятельства, когда имя заголовка может быть правильным именем, которое __FILE__ расширяется до.

10 голосов
/ 19 февраля 2011

Он всегда возвращает .c, где он используется, так как __LINE__ и __FILE__ разрешаются после препроцессора. Таким образом, вы можете написать макросы отладки, использующие __FILE__ и __LINE__, и указать, где появляются операторы отладки.

5 голосов
/ 19 февраля 2011

Расширение макроса (из всех макросов, а не только специальных, таких как __FILE__) выполняется после #include замены, поэтому да, на это поведение можно положиться.

4 голосов
/ 19 февраля 2011

Фактическим языком в стандарте является (§6.10.8):

__FILE__ Предполагаемое имя текущего исходного файла (литерал строки символов).

Поскольку расширение макроса происходит после обработки #include s, «текущий исходный файл» - это скомпилированный предварительно обработанный файл .c.

3 голосов
/ 19 февраля 2011

Этот макрос #define выполняет предварительную компиляцию буквенного замещения текста.Когда компилятор C попадает в ваш файл foo.c, он видит:

printf("%s", __FILE__);

, поэтому вы получаете foo.c.

...