Препроцессор всегда работает только с токенами.
Макрос не является функцией.Вы не передаете ему переменную (по значению).Вы передаете последовательность токенов.В STRINGIFY(MAX_STRING_LENGTH)
последовательность токенов равна MAX_STRING_LENGTH
, а в STRINGIFY(val)
это последовательность токенов val
.
MAX_STRING_LENGTH
сама является макросом, и из-за того, как STRINGIFY
определен для работы, макрос будет расширен препроцессором, прежде чем превратить его в строковый литерал.Таким образом, 20
, в свою очередь, является токеном, к которому применяется #
, и выдает "20"
в виде строкового литерала.
С другой стороны, val
не является макросом, препроцессорне собираюсь его расширять.Он будет сохранять последовательность токенов как val
.Факт val
- это имя переменной, значение которой для препроцессора означает ничто , оно заботится только о токенах.Таким образом, val
преобразуется в литерал "val"
.
Пример, который вы привели из другого поста, работает, потому что он расширился до следующего:
printf("var" "%d\n", var);
Имя переменной в #int
превращаетсяв литерал, нет волшебства, которое позволяет препроцессору читать значение переменной.Факт var 8
напечатан только потому, что var
передается в качестве аргумента printf
!Он печатается во время выполнения спецификатором %d
.
Наконец, при экспериментировании с препроцессором всегда полезно посмотреть исходный файл после выполнения prpeprocessing, но до его компиляции.Флаг gcc -E
(или эквивалент для вашего компилятора) может помочь вам сделать это.