Расширяется ли включенный заголовочный файл в файл C - PullRequest
3 голосов
/ 03 октября 2019

Возьмите следующую очень простую программу на C ниже. Насколько я понимаю, прекомпилятор сначала вызывается для расширения макросов и файлов заголовков и т. Д.

Насколько я понимаю, прекомпилятор сначала будет включать весь код (объявления) из файла заголовков stdio.h в C-файле перед компиляцией, поэтому размер C-файла больше, а номера строк различаются, поэтому вызов printf () будет дальше по файлу.

Если это так, почемуво время отладки номера строк по-прежнему верны?

#include <stdio.h>
int main()
{
    printf("Hello world!\n");
}

Ответы [ 3 ]

4 голосов
/ 03 октября 2019

Да, содержимое файла (ов) заголовка включено в текст.

Номера строк сохраняются, поскольку препроцессор имеет механизм для указания номеров строк :

#line 97 "original.c"
/* This is line 97 of the original C file */

Эти номера строк используются в сообщениях об ошибках. Как правило, компилятор использует сокращенную запись, которую он понимает - он часто пропускает слово line и добавляет дополнительную информацию - см., Например, GCC Вывод препроцессора .

Это можно увидеть, откомпилировав

#line 1000
pod variable = { 0 };

Поместите это в файл;попытаться скомпилировать его;обратите внимание, что компилятор жалуется на неизвестный тип pod в строке 1000, хотя в исходном файле это строка 2.

$ gcc -O -c original.c
original.c:1000:1: error: unknown type name ‘pod’
$

Вы можете запустить препроцессор и увидеть (объемный) вывод, используяОпция -E с GCC и большинством Unix-компиляторов C:

$ gcc -E original.c
# 1 "original.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "original.c"
# 1000 "original.c"
pod variable = { 0 };
$

Обратите внимание, что если бы я включил <stdio.h>, результат был бы намного больше (я получил 577 строк на одной машине - это меньше, чемЯ ожидал).

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


Прямо сейчас у меня проблема с некоторым кодом - мой тестcase:

/* Minimized GCC bug */

#include <assert.h>
#include <string.h>

extern int chk_arg(const char *arg);

int chk_arg(const char *arg)
{
    assert(strncmp(arg, "-", 1) == 0 && strncmp(arg, "--", 2) != 0);
    return (arg[1] == 'a');
}

Ошибка компиляции, которая меня беспокоит:

$   gcc -std=c11 -Wall -Wmissing-prototypes -Wstrict-prototypes -Wextra -pedantic -Werror -g -O3   -c gccbug.c
gccbug.c: In function ‘chk_arg’:
gccbug.c:10:5: error: string length ‘4587’ is greater than the length ‘4095’ ISO C99 compilers are required to support [-Werror=overlength-strings]
   10 |     assert(strncmp(arg, "-", 1) == 0 && strncmp(arg, "--", 2) != 0);
      |     ^~~~~~
cc1: all warnings being treated as errors
$

Непонятно, где строка из 4587 символов, пока вы не используете gcc -E:

int chk_arg(const char *arg)
{

# 10 "gccbug.c" 3 4
   (((__extension__ (__builtin_constant_p (
# 10 "gccbug.c"
   1
# 10 "gccbug.c" 3 4
   ) && ((__builtin_constant_p (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) && strlen (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) < ((size_t) (
# 10 "gccbug.c"
   1
# 10 "gccbug.c" 3 4
   ))) || (__builtin_constant_p (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) && strlen (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) < ((size_t) (
# 10 "gccbug.c"
   1
# 10 "gccbug.c" 3 4
   )))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) && __builtin_constant_p (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) && (__s1_len = strlen (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ), __s2_len = strlen (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ), (!((size_t)(const void *)((
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) == 1) || __s2_len >= 4)) ? __builtin_strcmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) : (__builtin_constant_p (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) && ((size_t)(const void *)((
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) == 1) && (__s1_len = strlen (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ), __s1_len < 4) ? (__builtin_constant_p (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) && ((size_t)(const void *)((
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) == 1) ? __builtin_strcmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ); register int __result = (((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) && ((size_t)(const void *)((
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) == 1) && (__s2_len = strlen (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ), __s2_len < 4) ? (__builtin_constant_p (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) && ((size_t)(const void *)((
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) == 1) ? __builtin_strcmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ) : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   ))[3]); } } __result; }))) : __builtin_strcmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   )))); }) : strncmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "-"
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   1
# 10 "gccbug.c" 3 4
   ))) 
# 10 "gccbug.c"
   == 0 && 
# 10 "gccbug.c" 3 4
   (__extension__ (__builtin_constant_p (
# 10 "gccbug.c"
   2
# 10 "gccbug.c" 3 4
   ) && ((__builtin_constant_p (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) && strlen (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) < ((size_t) (
# 10 "gccbug.c"
   2
# 10 "gccbug.c" 3 4
   ))) || (__builtin_constant_p (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) && strlen (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) < ((size_t) (
# 10 "gccbug.c"
   2
# 10 "gccbug.c" 3 4
   )))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) && __builtin_constant_p (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) && (__s1_len = strlen (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ), __s2_len = strlen (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ), (!((size_t)(const void *)((
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) == 1) || __s2_len >= 4)) ? __builtin_strcmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) : (__builtin_constant_p (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) && ((size_t)(const void *)((
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) == 1) && (__s1_len = strlen (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ), __s1_len < 4) ? (__builtin_constant_p (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) && ((size_t)(const void *)((
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) == 1) ? __builtin_strcmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ); register int __result = (((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) && ((size_t)(const void *)((
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) == 1) && (__s2_len = strlen (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ), __s2_len < 4) ? (__builtin_constant_p (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) && ((size_t)(const void *)((
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) + 1) - (size_t)(const void *)(
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ) == 1) ? __builtin_strcmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ) : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   ); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   ))[3]); } } __result; }))) : __builtin_strcmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   )))); }) : strncmp (
# 10 "gccbug.c"
   arg
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   "--"
# 10 "gccbug.c" 3 4
   , 
# 10 "gccbug.c"
   2
# 10 "gccbug.c" 3 4
   ))) 
# 10 "gccbug.c"
   != 0
# 10 "gccbug.c" 3 4
   ) ? (void) (0) : (__assert_fail (
# 10 "gccbug.c"
   "(__extension__ (__builtin_constant_p (1) && ((__builtin_constant_p (arg) && strlen (arg) < ((size_t) (1))) || (__builtin_constant_p (\"-\") && strlen (\"-\") < ((size_t) (1)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (arg) && __builtin_constant_p (\"-\") && (__s1_len = strlen (arg), __s2_len = strlen (\"-\"), (!((size_t)(const void *)((arg) + 1) - (size_t)(const void *)(arg) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((\"-\") + 1) - (size_t)(const void *)(\"-\") == 1) || __s2_len >= 4)) ? __builtin_strcmp (arg, \"-\") : (__builtin_constant_p (arg) && ((size_t)(const void *)((arg) + 1) - (size_t)(const void *)(arg) == 1) && (__s1_len = strlen (arg), __s1_len < 4) ? (__builtin_constant_p (\"-\") && ((size_t)(const void *)((\"-\") + 1) - (size_t)(const void *)(\"-\") == 1) ? __builtin_strcmp (arg, \"-\") : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (\"-\"); register int __result = (((__const unsigned char *) (__const char *) (arg))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (arg))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (arg))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) (arg))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (\"-\") && ((size_t)(const void *)((\"-\") + 1) - (size_t)(const void *)(\"-\") == 1) && (__s2_len = strlen (\"-\"), __s2_len < 4) ? (__builtin_constant_p (arg) && ((size_t)(const void *)((arg) + 1) - (size_t)(const void *)(arg) == 1) ? __builtin_strcmp (arg, \"-\") : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) (arg); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (\"-\"))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (\"-\"))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (\"-\"))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (\"-\"))[3]); } } __result; }))) : __builtin_strcmp (arg, \"-\")))); }) : strncmp (arg, \"-\", 1))) == 0 && (__extension__ (__builtin_constant_p (2) && ((__builtin_constant_p (arg) && strlen (arg) < ((size_t) (2))) || (__builtin_constant_p (\"--\") && strlen (\"--\") < ((size_t) (2)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (arg) && __builtin_constant_p (\"--\") && (__s1_len = strlen (arg), __s2_len = strlen (\"--\"), (!((size_t)(const void *)((arg) + 1) - (size_t)(const void *)(arg) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((\"--\") + 1) - (size_t)(const void *)(\"--\") == 1) || __s2_len >= 4)) ? __builtin_strcmp (arg, \"--\") : (__builtin_constant_p (arg) && ((size_t)(const void *)((arg) + 1) - (size_t)(const void *)(arg) == 1) && (__s1_len = strlen (arg), __s1_len < 4) ? (__builtin_constant_p (\"--\") && ((size_t)(const void *)((\"--\") + 1) - (size_t)(const void *)(\"--\") == 1) ? __builtin_strcmp (arg, \"--\") : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (\"--\"); register int __result = (((__const unsigned char *) (__const char *) (arg))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (arg))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (arg))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) (arg))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (\"--\") && ((size_t)(const void *)((\"--\") + 1) - (size_t)(const void *)(\"--\") == 1) && (__s2_len = strlen (\"--\"), __s2_len < 4) ? (__builtin_constant_p (arg) && ((size_t)(const void *)((arg) + 1) - (size_t)(const void *)(arg) == 1) ? __builtin_strcmp (arg, \"--\") : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) (arg); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (\"--\"))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (\"--\"))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (\"--\"))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (\"--\"))[3]); } } __result; }))) : __builtin_strcmp (arg, \"--\")))); }) : strncmp (arg, \"--\", 2))) != 0"
# 10 "gccbug.c" 3 4
   , "gccbug.c", 10, __PRETTY_FUNCTION__), (void) (0)))
# 10 "gccbug.c"
                                                                  ;
    return (arg[1] == 'a');
}

Ой! Я не знаю, распознал ли я это утверждение, если оно сработало - оно не похоже на текст в исходном коде, это точно! (Это из GCC 9.2.0, работающего на древнем RHEL 5 Linux.)

2 голосов
/ 03 октября 2019

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

0 голосов
/ 03 октября 2019

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

Учитывая эти файлы:

x1.h:

int x = 4;

int printf(const char *, ...);

x1.c:

#include "x1.h"

int main()
{
    printf("x=%d\n", x);
    return 0;
}

Препроцессор для gcc выдает следующее :

# 1 "x1.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "x1.c"
# 1 "x1.h" 1
int x;

int printf(const char *, ...);
# 2 "x1.c" 2

int main()
{
    printf("x=%d\n", x);
    return 0;
}

Каждая строка начинается с # включает номер текущей строки, имя текущего исходного файла, а также некоторые дополнительные флаги.

В начале вы видите, что source: line установлен на x1.c:1, который является началом основного исходного файла,Затем вы можете увидеть прямо перед включением x1.h, что source: line установлен на x1.h:1. После того как строка include source: установлена ​​на x1.c:2.

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

...