1. Си / Говнокод #17767

    +135

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    #define   CONC_LINE(a)  CONC(a, __LINE__)
    #define   CONC(a, b)  __CONC(a, b)
    #define __CONC(a, b)  a##b
    // ...
    int CONC_LINE(name);

    Способ присовокупить к названию переменной номер строки, где её объявили.
    Объясните кто-нибудь, почему #define CONC_LINE (a) __CONC ( a, __LINE__ ) дает: name__LINE__?

    Запостил: refactor, 11 Марта 2015

    Комментарии (11) RSS

    • Код не говно. Говно в самом сишкоблядском недопрепроцессоре :(

      > Объясните
      Если кратко - то # и ## блокируют рекурсивное раскрытие своих аргументов.
      Ответить
      • Дай ссылку на систему программирования с ЧОТКИМ препроцессором
        Ответить
        • Вот нормальные макро:
          https://en.wikipedia.org/wiki/Lisp_%28programming_language%29
          https://en.wikipedia.org/wiki/Scheme_%28programming_language%29

          P.S. Да даже m4 лучше, чем сишный препроцессор.
          P.P.S. Только, пожалуйста, не говори мне, что я "ниасилил" сишный препроцессор.
          Ответить
          • Семантическая рекурсивность этих языков "Данные это код, код это данные" конечно впечатляет - там, я так понимаю, вообще сложно выделить препроцессор от всего остального. Поэтому предположу что твой пример некорректен.
            Ответить
            • Ну ок, если чисто препроцессор нужен, то взгляни на встроенный в nasm. По сравнению с сишным - небо и земля.
              Ответить
              • P.S. Вменяемая рекурсия и циклы, генератор уникальных имён (да-да, костыль, с которого начался этот тред, там просто не нужен), перегрузка по количеству аргументов, арифметика, переменное число параметров...

                Само собой, асму хороший препроцессор важнее, чем сишке. Но сишный, имхо, сделан вообще на отъебись.
                Ответить
    • Если подробнее, то как-то так:

      В правильном коде препроцессор видит CONC_LINE(name) и заменяет его на CONC(name, __LINE__) при этом раскрыв все макросы в name (которых там нет). На результате запускается повторный скан: препроцессор видит CONC(name, __LINE) и заменяет его на __CONC(name, 42), раскрыв все макросы в name (которых там нет) и __LINE__ (который раскроется в номер строки). На результате запускается еще один скан: препроцессор видит __CONC(name, 42) и заменяет его на name42 НЕ раскрывая макросы в name и 42.

      А если сделать сразу __CONC, то получится так: препроцессор видит CONC_LINE(name) и заменяет его на __CONC(name, __LINE__) предварительно раскрыв все макро в name (которых там нет). На втором проходе он видит __CONC(name, __LINE__) и заменяет его на name__LINE__ НЕ раскрывая макросы в name и __LINE__.
      Ответить
      • Ты крутой.
        мимо-скрипт-макака
        Ответить
        • похоже что борманд опять начал на ночь читать сырцы boost_pp.
          Ответить
          • Не, я макросы давно уже не юзал. Разве что инклуд да ифдеф+дефайн вверху ашки... В плюсовом коде, слава богу, они почти не нужны.
            Ответить
    • > COCOCONC
      Боян много раз
      Ответить

    Добавить комментарий