Няшная / Говнокод #27525 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

typedef struct list list;

struct list
{
  list* next;
  uint32_t data;
};

#define ADD_LIST(ptr, val) \
do { \
  (ptr)->next = (list *)alloca(sizeof(list)); \
  (ptr)->next->data = val; \
  (ptr)->next->next = NULL;\
} while (0)

// https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
#define INIT_LIST(val) \
({ \
  list *INIT_LIST = (list *)alloca(sizeof(list)); \
  INIT_LIST->data = val; \
  INIT_LIST->next = NULL; \
  INIT_LIST; \
})


int main(void)
{
  list *a = INIT_LIST(5);
  ADD_LIST(a,10);
  ADD_LIST(a->next,15);
  ADD_LIST(a->next->next,20);
  ADD_LIST(a->next->next->next,25);
  ADD_LIST(a->next->next->next->next,30);

  for(list *ptr = a; ptr != NULL; ptr = ptr->next)
  {
    printf("%d ", ptr->data);
  }

  return EXIT_SUCCESS;
}

А можно ли в крестоговне так сделать без Сишного Препроцессора?

Запостил: j123123 j123123, (Updated )

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

    • напиши свой помпилятор... вот у меня есть
      mlir::Value newStringValue = rewriter.create<LLVM::AllocaOp>(op->getLoc(), i8PtrTy, size, true);
      Ответить
  • Переписал тебе код, проверь:
    { \
      (ptr)->next = (list *)alloca(sizeof(list)); \
      (ptr)->next->data = val; \
      (ptr)->next->next = NULL;\
    }
    Ответить
      • Чем копипаст этого блока отличается от копипаста того цикла?
        Ответить
              • Классика, чтобы не думать и течь, используя вызов макроса как вызов функции в ветвях условного оператора без фигурных скобок.

                Кстати, есть пример, когда do { ... } while(0) имеет смысл в обычном коде: break или continue досрочно завершает выполнение блока, и не нужно лепить goto или косяки вложенных ифов.
                Ответить
              • В данной программе можно обойтись и обычным «{}». У тебя «overengineering», проверть.
                Ответить
                • Заповеди макроёбства не просто так придуманы. Без do while точка с запятой лишней будет.
                  Ответить
                          • На стаковерфлоу написано, что будет багор, т.к. else отвяжется от if.

                            А, нет, это про другое написано.

                            > It doesn't help to wrap things in curly braces within the macro, because a semicolon after the braces is syntactically incorrect.

                            Решение проблемы довольно просто́: не ставить «семиколон» после мокроса.
                            Ответить
                            • Ну и сиди потом думай где ставить, где не ставить...

                              Именно поэтому я за do while.

                              Но, повторюсь, в твоём примере expression а не statement.
                              Ответить
                              • > Ну и сиди потом думай где ставить, где не ставить

                                Это, кстати, даже к лучшему: вот захочешь ты взять указатель на функцию... А это мокрос. Да и правило простое: после мокроса скмиколон не ставится.
                                Ответить
                            • Блин ну вы о чём?

                              Второй макрос же в ({...}) завернут. Все норм с ним, просто гнутое расширение требует.
                              Ответить
                              • > ({...})

                                Оператор post-goatse.

                                А разве он не в «{}» завёрнут? Или мокрос кончается на первой попавшейся пустой линии?

                                > Линии

                                Ну вот, скоро начну и «аппликации» говорить (((
                                Ответить
                                    • А как различить их, кстати? body аргумент и body тело.
                                      Ответить
                                      • Х.з., видимо это гнутое расширение не работает на макросах без аргументов.
                                        Ответить
                                        • Я подозреваю, что макрос ближайшие скобочки всегда считает своим аргументом, а на тело отводится то, что осталось (вне зависимости от гну/негну). Т. е. макрос со скобочками в теле, но без аргументов в принципе объявить нельзя.
                                          Ответить
                                          • Да нет, работает. Отличает по пробелу между именем макроса и круглой скобочкой, судя по всему. Если пробела нету -- аргументы. Если есть -- значит просто тело со скобочками.
                                            Ответить
                                            • Точно! Забыл про пробел в макросе. Я на это попадался...

                                              Привык, что сишке/крестам плевать на пробелы.
                                              Ответить
                                              • А вот в «Nim» пробелы очень важны. Как вы думаете, что выведет этот код?

                                                echo 2+2 * 3+3
                                                Ответить
                                                • Не знаю, но есть подозрение, что у пробелов низкий приоритет, т. е. он посчитает это как
                                                  echo (2+2) * (3+3)

                                                  Так?

                                                  А звёздочка будет означать по-прежнему умножение или что-то другое?
                                                  Ответить
    • Сразу видно, что ты математик. Раскрыть препроцессор - задача формально решена.
      Ответить
    • зачем писать код который ни один анализатор не возмет... это просто выстрелить себе в ногу из дробовика
      Ответить
      • Зачем мне подстраивать свой код под всякие заедушные анализаторы? Если какой-то там анализатор чего-то не понимает в моем коде, то это проблема анализатора
        Ответить
  • Надо было в цикле ноды создавать, имхо, тогда идея лучше бы раскрылась. А то сейчас можно и без alloca() на обычных локалках переписать.
    Ответить
    • Только надо было бы придумывать каждой локалке уникальное имя. А еще локалки дохнут при выходе из скоупа, а выделенная через alloca() хрень дохнет только при выходе из функции.
      Ответить
      • Хотя нафиг локалки то, std::array да и всё. Или что-то своё похожее налепить. Для статичных структур нету смысла городить костыли через alloca().

        Всё-таки тут надо было именно динамичный пример показать, что ты создаёшь ноды на лету и не знаешь о них ничего заранее.
        Ответить
            • https://wandbox.org/permlink/QSe51o1Mt6kuuBNg вот, улучшил чтоб с scanf(). Немного поменял макросы.

              #define ADD_LIST(ptr, val) \
              do { \
                (ptr)->data = val; \
                (ptr)->next = (list *)alloca(sizeof(list)); \
                (ptr)->next->next = NULL;\
              } while (0)
              
              // https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
              #define INIT_LIST() \
              ({ \
                list *INIT_LIST = (list *)alloca(sizeof(list)); \
                INIT_LIST->next = NULL; \
                INIT_LIST; \
              })


              Теперь список с нулем элементов это не когда указатель на такой список равен NULL, а когда ->next равен NULL. И INIT_LIST() теперь нихрена не принимает в качестве первого значения
              Ответить
              • Ну вот теперь официально можно заявлять что крестобляди соснули т.к. alloca() нельзя вернуть из вложенных функций.
                Ответить
                • надо редактировать фрейм поинтеры... - причем срочно
                  Ответить
                  • У меня не получилось, надо генератор эпилога в самом конпеляторе править. Иначе остаётся тонкий момент в который может ебануть прерывание сигнал и всё испортить.
                    Ответить
              • ого, динамическая структура на стеке это круто;) Почти как троллейбус из булки
                Ответить
                • Не забывай, что в контроллере у меня может не быть никакого хипа.
                  Ответить
                    • В стат. памяти ты должен заранее знать, сколько там байтиков надо. А тут их хуй знает сколько надо.
                      Ответить
                      • Почему не выделить сразу по максимуму?
                        Ты ведь тоже можешь стековерфлоу схватить
                        Ответить
                          • Вся статическая память минус иницилизорванная минус BSS, не?
                            Ответить
                            • Что еще за "инициализированная"? Что за "BSS"? Инициализированная в RAM или в flash? В разных контроллерах у тебя flash бывает и в одном адресном пространстве с RAM, и в разных. В RAM памяти у тебя при включении обычно будет всякий рандом, и кстати его можно использовать как seed в ГПСЧ каком-нибудь.

                              https://hackaday.com/2015/06/29/true-random-number-generator-for-a-true-hacker/
                              > When power is applied to the MCU, its internal volatile RAM has unknown contents. Each flip-flop will be preset to a 0 or 1 state – a consequence of the imperfection of internal circuits, power supply glitches, surrounding current flow, or thermal (or even quantum) noise. That’s why the content of RAM is different each time it is powered on.

                              Так что для BSS тебе нужен код зануления, а дня инициализированной (если это RAM) тебе нужен код, который из флеша перекопирует в RAM.
                              Ответить
                            • Кстати вот в контроллерах FX2 и FX2LP никакого встроенного EEPROM вообще нет. https://www.cypress.com/file/138911/download
                              During the power-up sequence, internal logic checks the I2C port
                              for the connection of an EEPROM whose first byte is either 0xC0
                              or 0xC2. If found, it uses the VID/PID/DID values in the EEPROM
                              in place of the internally stored values (0xC0), or it boot-loads the
                              EEPROM contents into internal RAM (0xC2). If no EEPROM is
                              detected, FX2LP enumerates using internally stored descriptors.
                              The  default  ID  values  for  FX2LP  are  VID/PID/DID  (0x04B4,
                              0x8613, 0xAxxx where xxx = Chip revision)

                              Есть всякие дешевые лог. анализаторы на базе этого контроллера, и там прошивка в оперативку заливается по USB при каждом включении.
                              Ответить

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

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

    А не использовать ли нам bbcode?


    8