C-язык: значение оператора "#"?

Этот код может быть скомпилирован gcc -g -o main main.c, никаких предупреждений.

// main.c
# 41 "stdio.h"
# 22
#
int main(void){
    (void)printf("foo");
    return 0;
}

Мой вопрос:

  • В чем смысл оператора "#" перед "включить". Мы используем #include <stdio.h> для включения файла заголовка, почему бы не include <stdio.h>?

  • Почему # 22 или # 41 может быть скомпилирован, я никогда не видел его раньше.

Кто-нибудь может мне помочь?

Ответы

Ответ 1

Это выглядит как результат препроцессора. Строка

# 41 "stdio.h"

можно интерпретировать следующим образом:

  • 41 имеет значение:

Указывает номер строки, который должен быть указан для следующей строки ввода. Последующие строки подсчитываются из белья.

  • "stdio.h" - это просто имя файла, из которого берутся строки.

Следующая строка и все последующие строки как сообщается, из файла, который он указывает, до тех пор, пока что-то еще не произойдет измените это. filename интерпретируется в соответствии с обычными правилами для строки константа: экраны обратной косой черты интерпретируются.

И вся эта информация взята из https://gcc.gnu.org/onlinedocs/cpp/Line-Control.html#Line-Control и https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html#Preprocessor-Output

Для одиночного #:

Нулевая директива состоит из '#, за которой следует новая строка, с пробелом (включая комментарии) между ними. Директива "null" понимается как директива предварительной обработки, но не влияет на выход препроцессора. Основное значение существования нулевой директивы состоит в том, что строка ввода, состоящая только из "#", не будет выводить результат, а не строки вывода, содержащей только "#". Предположительно, некоторые старые C-программы содержат такие строки.

взято из https://gcc.gnu.org/onlinedocs/cpp/Other-Directives.html#Other-Directives

Ответ 2

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

Если за # следуют что-либо, кроме include, define, undef, line, error или pragma, то это не директива (6.10p1), и игнорируется.

Это означает, что # в начале строки - это простой способ для компилятора передать информацию между этапами перевода; здесь он используется для передачи информации о файле источника и номера строки.