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

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
      int a[4] = {1, 2, 3, 4};
      int (*a_p1)[4] = (int (*)[4])a;
      int (*a_p2)[4] = &a;
      for(size_t i = 0; i < 4; ++i)
      {
        printf("%p -> %d; %p -> %d\n", &(*a_p1)[i], (*a_p1)[i], &(*a_p1)[i], (*a_p2)[i]);
      }
      return EXIT_SUCCESS;
    }

    Вот такой вывод:
    0x7ffee4ebd950 -> 1; 0x7ffee4ebd950 -> 1
    0x7ffee4ebd954 -> 2; 0x7ffee4ebd954 -> 2
    0x7ffee4ebd958 -> 3; 0x7ffee4ebd958 -> 3
    0x7ffee4ebd95c -> 4; 0x7ffee4ebd95c -> 4

    Запостил: j123123, 14 Января 2022

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

    • Бля, неправильно написал. Короче вот
      printf("%p -> %d; %p -> %d\n", &(*a_p1)[i], (*a_p1)[i], &(*a_p2)[i], (*a_p2)[i]);

      Как думаете, почему
      int (*a_p1)[4] = (int (*)[4])a;
      и
      int (*a_p2)[4] = &a;
      означают одну и ту же хуйню? Или есть какая-то разница?
      Ответить
      • может совпало так.. а может это в контролерах только
        Ответить
      • UPD: хуйню сказал, спать хочу, херово мне. Игнорируйте этот твит.
        Ответить
      • а — указывает на первый элемент массива (int*)
        &a — указывает на сам массив (int(*)[4])
        (int (*)[4])a — у a и &a значения одинаковые, но разные типы, приводим, получается однохуственно

        Верно?
        Ответить
        • Ну тип того, массив неявно кастится в указатель на свои элементы.
          Ответить
        • Собственно, вот:
          #include <stdio.h>
          #include <stdlib.h>
          
          int main()
          {
            int a[4] = {1, 2, 3, 4};
            printf("(%p == %p) is %s\n", a, &a, ((void *)a == (void *)&a) ? "true" : "false");
            return EXIT_SUCCESS;
          }

          Так точно: (0x7fffc4da4ea0 == 0x7fffc4da4ea0) is true
          Ответить
          • В сишке устроили путаницу с массивами.

            *a и a[0] означает одно и то же: первый элемент массива (хотя есть нюанс с sizeof в зависимости от места хранения).

            a и &a означают одно и то же, если a — массив.

            Но если тот же самый массив завернуть в структуру...
            Ответить
            • Можно вообще отказаться от "массивов". Например, для выделения хуеты на стеке можно вместо
              int a[4] = {1,2,3,4};
              // писать хуйню вида
              int *a = INIT_INT_ARR(alloca(sizeof(int)*4), 1, 2, 3, 4); // типа тут выделяется фукнцией alloca() массив на стеке, и его инициализирует какое-то макроговно

              Только для глобальных и статических локальных массивов нужно еще какое-то особое говно, типа компилтайм-аллокации
              Ответить
              • Нужны директивы, чтоб срать в объектный код.
                Ответить
              • Ну и еще выделенная через alloca() память освобождается по завершении функции только, а массивы освобождаются по завершении скоупа, т.е.
                void shit()
                {
                  int *a;
                  int *b;
                  {
                    int *a_s = alloca(sizeof(int));
                    a = a_s;
                    int b_s[1];
                    b = b_s;
                  }
                  *a = 666; // норм
                  *b = 666; // ошибка потому что b_s уже невалидная хуйня
                }


                Так что во всех случаях тупо заменить локальные массивы alloca()-хуйней не выйдет. В каком-нибудь цикле это alloca() может весь стек выжрать запросто
                Ответить
                • А ты аллоцируй их только в начале, как в староняшной.
                  Ответить
                  • Можно всякие там скоупы внутри функций запретить вообще, и на каждый чих делать новые функции. Т.е вместо
                    for(size_t i = 0; i < x; i++)
                    {
                      size_t a[3] = {i, i+1, i+2};
                      ...
                      ...
                      ...
                    }
                    
                    // делать
                    for(size_t i = 0; i < x; i++)
                      some_func(i, прочая_хрень); // и вот там уже alloca() будет точным аналогом локального массива
                    Ответить
                    • for(size_t i = 0; i < x; i++)
                        function(i, хрень) {
                          int *a_s = alloca(sizeof(int));
                          ...
                        } (i, прочая_хрень);
                      Ответить
                  • Там же в начале блока было
                    Ответить
            • Да в общем то свойства самого массива останутся, если обращатся к нему по struc.arr, а копирование присваиванием — это уже свойство структуры.
              Ответить
            • Но при этом &&a, &&&a написать все равно нельзя. Может ли омниидемпотентность быть ограниченной?
              Ответить
              • Чему равен адрес адреса?
                Ответить
                • Ты что, почтальон?
                  Ответить
                • Адрес адреса равен адресу той хрени, где записан адрес, это же очевидно. Можно сделать адрес на то, где этот сам адрес записан, например:
                  void *ptr = &ptr;

                  Можно такой указатель кастовать в двойной указатель на void и разыменовывать бесконечное количество раз.
                  printf("%p\n", p);
                  p = *(void **)p;
                  printf("%p\n", p);
                  p = *(void **)p;
                  printf("%p\n", p);
                  p = *(void **)p;
                  printf("%p\n", p);
                  p = *(void **)p;
                  printf("%p\n", p);
                  p = *(void **)p;
                  printf("%p\n", p);
                  Ответить
                  • > Адрес адреса равен адресу той хрени, где записан адрес
                    Это уже будет адрес ячейки памяти. А адрес — это именно само значение, у него не может быть адреса, так же как и у, например, числа 42. Ты же не можешь написать &42
                    Ответить
                    • Нужно просканировать всю оперативку в поисках числа 42 и вернуть адрес первого найденного экземпляра.
                      Ответить
                      • Можно положить 42 в известное место и вернуть его адрес.
                        Ответить
                    • вы про райт валью?
                      Ответить
                      • Аха
                        Ответить
                      • Кстати, почему разыменование может быть и rvalue, и lvalue (например, *pituh = 42;), а взятие адреса только rvalue?

                        Хочу так:
                        &pituh = some_address;

                        И пусть компилятор (рантайм) перемещает переменную, как хочет.
                        Ответить
                        • > &pituh = some_address;
                          Это в смысле мы скопировали петуха в some_address, и потёрли оригинала?
                          Ответить
                        • Это всё хуйня. Вот почему присваивание идёт справа налево? Я хочу написать
                          42 = pituh;
                          и пусть компилятор разбирается сам.
                          Ответить
                          • Можно писать сверху вниз:
                            pituh
                            =
                            42;
                            Ответить
                          • Надо где-нибудь спиздить армянскую идентичность и преимушно мирно протестовать у центрального комитета.

                            https://i.postimg.cc/2843vf1y/7-5.jpg
                            Ответить
                          • В языке «R» можно писать pituh <- 42 или 42 -> pituh.

                            А в языке «METAFONT» Кнута есть присвоения (:=, как в Паскале) и уравнения. Уравнения пытаются найти значения тех переменных, которые в данный момент undefined. Например:
                            kurochka := 13;
                            pituh + 42 = kurochka + 265;

                            Этот код найдёт значение pituh, потому что значение kurochka уже известно.
                            Ответить
                            • > уравнения
                              Вот! То что я и имел в виду под «пусть компилятор разбирается». Сразу видно — ма-те-ма-тик писал, а не случайный питух.
                              Ответить
                              • В Метафонте помимо состояний defined и undefined есть третье состояние — связанная переменная. То есть он может решать не только уравнения, но и системы уравнений.

                                x + y = 120;


                                Теперь x и y — связанные переменные. Если присвоить значение x, он посчитает y.

                                Если же написать новое уравнение, в котором указаны обе переменные, то он их обе посчитает:
                                x - y = 20;


                                Системы линейных уравнений он точно решать умеет. Про нелинейные не знаю.
                                Ответить
                            • > А в языке «METAFONT» Кнута есть присвоения (:=, как в Паскале) и уравнения.

                              Тут вполне достаточно и одних лишь уравнений. К тому же это все отлично решается в SMT-солверах, например тут https://compsys-tools.ens-lyon.fr/z3/index.php
                              (declare-fun kurochka () Int)
                              (declare-fun pituh () Int)
                              
                              ; Constraints
                              
                              ; kurochka := 13
                              (assert (= kurochka 13))
                              
                              ; pituh + 42 = kurochka + 265
                              (assert (=
                               (+ pituh 42)
                               (+ kurochka 265)
                              ))
                              
                              ; Solve
                              (check-sat)
                              (get-model)

                              результат:
                              sat
                              (model 
                                (define-fun pituh () Int
                                  236)
                                (define-fun kurochka () Int
                                  13)
                              )
                              Ответить
                              • Наверняка это можно и в "Coq" автоматически доказать какими-то банальными тактиками.
                                Ответить
                              • Присвоение позволяет забыть старое состояние. В императивных ЯП это нужно.

                                Кроме того, бывают сложные случаи типа x = y. Тут нужно выяснять, какая из переменных undefined, какая связанная, какая известна. А если написать x:=y, то состояние x можно проигнорировать и пытаться вычислить y в любом случае.

                                В чисто декларативных ЯП таких ситуаций не возникает.
                                Ответить
                                • Если смешивать декларативщину и императивщину, есть очень немалый риск получить какую-то неконсистентную хуйню
                                  Ответить
                                  • > Если смешивать декларативщину и императивщину, есть очень немалый риск получить какую-то неконсистентную хуйню

                                    Лолбоёбы уже смешали имперации с функци-анальщиной.

                                    Что получили в итоге? Неочевидные правила захвата пельменных (хорошо только в «PHP»), просто говняные отвратно выглядящие языки (привет Scala-хуесосам).

                                    Проблема вылезла в куче недоязычков от С# до JS.
                                    let её никак не решает.
                                    let x;
                                    for (x=0;x<3;++x) {
                                       setTimeout(() => console.log(x), 1); 
                                    }
                                    3
                                    3
                                    3

                                    Если где-то проебал var/let пельменная может приехать из внешнего конь-текста.

                                    А всё поцчему?
                                    Вместо того чтобы писать и циклы в едином функциональном стиле c колобками
                                    array.forEach((x)=>...)

                                    Устроили смешивание образов императивного и функционального.
                                    Ответить
                                  • > смешивать декларативщину и императивщину

                                    Сначала жертву учат писать императивно. Говорят, что императивный стиль — это хорошо, потому что идеально ложится на железо.

                                    Затем жертву убеждают что использование объектно-ориентированного подхода позволяет сократить стоимость разработки на 12.6% по сравнению с устаревшим процедурным подходом.

                                    Затем жертве говорят, что ООП это уже не модно и нужно использовать функциональный стиль.

                                    Зомбирующий говорит: «Имперации! Функциклонги!»

                                    Ассистенты зомбирующего повторяют: «Декларативность! ООП!»

                                    Таким образом обеспечивается усиление смешивания парадигм.

                                    Затем моду меняют.

                                    Основной смысл - оглупление. Бывают случаи очень сильного падения уровня интеллекта в результате применения этой методики.
                                    Ответить
                          • > Вот почему присваивание идёт справа налево? Я хочу написать

                            > 42 = pituh;
                            #include <stdio.h>
                            #include <stdbool.h>
                            
                            int main() {
                            bool isAdmin = false;
                            /* begin admins only */ if (isAdmin) {
                            printf("You are an admin.\n");
                            /* end admins only */ }
                            return 0;
                            }
                            
                            The trick is to use Unicode control characters to reorder tokens in source code at the encoding level.
                            These visually reordered tokens can be used to display logic that, while semantically correct, diverges from the logic presented by the logical ordering of source code tokens.
                            Compilers and interpreters adhere to the logical ordering of source code, not the visual order.
                            
                            The attack is to use control characters embedded in comments and strings to reorder source code characters in a way that changes its logic.
                            The previous example, for instance, works by making a comment appear as if it were code:
                            /* if (isAdmin) { begin admins only */ 
                            Adversaries can leverage this deception to commit vulnerabilities into code that will not be seen by human reviewers.
                            
                            This attack pattern is tracked as CVE-2021-42574.
                            
                            https://trojansource.codes/
                            Ответить
                            • Unicode has support for both left-to-right and right-to-left languages, and to
                              aid writing left-to-right words inside a right-to-left sentence (or vice versa)
                              it also features invisible codepoints called "bidirectional override".
                              
                              These codepoints are normally used across the Internet to embed a word inside a
                              sentence of another language (with a different text direction), but it was
                              reported to us that they could be used to manipulate how source code is
                              displayed in some editors and code review tools, leading to the reviewed code
                              being different than the compiled code. This is especially bad if the whole
                              team relies on bidirectional-aware tooling.
                              
                              As an example, the following snippet (with `{U+NNNN}` replaced with the Unicode
                              codepoint `NNNN`):
                              
                              ```rust
                              if access_level != "user{U+202E} {U+2066}// Check if admin{U+2069} {U+2066}" {
                              ```
                              
                              ...would be rendered by bidirectional-aware tools as:
                              
                              ```rust
                              if access_level != "user" { // Check if admin
                              ```
                              Ответить
                              • То есть программисту нужен тупейший текстовый редактор, который отображает один кодпоинт на одно знакоместо и игнорирует RLM, zero-width joiner и прочую питушню. Арабы и евреи соснут, да...
                                Ответить
                                • > программисту нужен тупейший текстовый редактор, который отображает один кодпоинт на одно знакоместо и игнорирует RLM, zero-width joiner и прочую питушню

                                  Dubbed Trojan Source, the attack impacts many of the compilers, interpreters, code editors, and code repository frontend services used by software developers. Malicious actors could leverage the method to create code that would be displayed one way in code editors, but be interpreted differently by the compiler.

                                  C, C++, C#, JavaScript, Java, Rust, Go, and Python have been found to be impacted, as well as VS Code, Atom, SublimeText, Notepad, vim, emacs, GitHub and BitBucket.


                                  Соснули все.

                                  Вот именно поэтому я за «ed».
                                  https://govnokod.ru/26423#comment527017
                                  Ответить
                                  • Пойдёт любой редактор на «Turbo Vision» без поддержки «Unicode». Правда, строковые литералы придётся редактировать в другом...
                                    Ответить
                                • Реальный пример (проверка подсветки ГК):
                                  #include <stdio.h>
                                  
                                  int main() {
                                      /* Say bagor; newline⁧ /*/ return 0 ;
                                      printf("Kakoi bagor )))");
                                      return 0;
                                  }

                                  https://ideone.com/dGF2bH
                                  Ответить
                                  • Проверил в vim и busybox vi.

                                    Оба показывают нормально (просто игнорят уникод).
                                    more тоже хорош
                                    /* Say bagor; newline /*/ return 0 ;

                                    А обожаемый мною less идеален:
                                    #include <stdio.h>
                                    
                                    int main() {
                                        /* Say bagor; newline<U+2067> /*/ return 0 ;
                                        printf("Kakoi bagor )))");
                                        return 0;
                                    }

                                    А вот сцинтильная заедушатина сливает, да.
                                    Ответить
                                  • /*/ в «сишке» и (*) в «Паскале» — это мина замедленного действия.
                                    Ответить
                                    • Ответить
                                    • > /*/ в «сишке» и (*) в «Паскале» — это мина замедленного действия.

                                      Опровергаю. И без них можно обосраться:
                                      #include <stdio.h>
                                      #include <string.h>
                                      
                                      int main() 
                                      {
                                          char* lalka = "bagor";
                                          if (0!=strcmp(lalka, "bagor‮ ⁦// comment⁩ ⁦")) {
                                              puts("Kakoi gabor )))");
                                          }
                                          if (0!=strcmp(lalka, "bagor")){
                                              puts("Pituz!");
                                          }    
                                          return 0;
                                      }
                                      https://ideone.com/RiM3LX
                                      Success	#stdin #stdout 
                                      
                                      Kakoi gabor )))
                                      Ответить
                                      • Опровержение не принято. /*/ всё равно является миной, потому что может бабахнуть после внесения правок.

                                        Это не отменяет того, что существуют другие способы обосраться.
                                        Ответить
                                    • > мина замедленного действия

                                      Мина замедленного действия это такая мина, на которую допустим случайно наступил, проходя мимо, а она только через час взорвется?
                                      Ответить
                                      • Пожалуй, я придумал неудачный термин. Тут должно бабахнуть сразу после наступания.
                                        Ответить
                                      • С комментариями в сишке бывают какие-то багры. Например, если строку с концом комментария */ закомментировать однострочником //

                                        Поэтому ненужный код лучше прятать в #ifdef, а не в комментарии.
                                        Ответить
                                  • проверка подсветки ГК (без спец. символов return не горит синим)
                                    #include <stdio.h>
                                    
                                    int main() {
                                        /* Say bagor; newline  return 0 ; /*/
                                        printf("Kakoi bagor)))");
                                        return 0;
                                    }
                                    Ответить
                                    • На ГК две подсветки (переключаются в личной кабинке): Geshi (server-side, PHP) и HighlightJS (client-side). Они показывают разные результаты.
                                      Ответить
                                • > То есть программисту нужен тупейший текстовый редактор, который отображает один кодпоинт на одно знакоместо и игнорирует RLM, zero-width joiner и прочую питушню.

                                  Программисту достаточно говноскриптом пройтись по всем исходникам и выпилить нахер всю эту питушню с отзеркаливанием текста. Можно в компилятор даже встроить какую-то хуйню, чтоб он варнинг писал на такое.
                                  Ответить
                                  • Даже если она в строковых литералах? Хотя в литералах их можно заэскейпить.
                                    Ответить
                                    • unicode_real_escape_string
                                      Ответить
                                    • Можно ещё оттранслировать все эти тАотБжтБйтБж, переворачивая текст как надо. Тогда содержимое будет соответствовать тому, как кот отоброжуется. Можно будет запускать такие программы и они будут делать то, что ты прочитал
                                      Ответить
                                    • > Даже если она в строковых литералах?
                                      А нахуя она в строковых литералах? Если у тебя RTL и прочая питушня в строке, то это скорее всего должно хранится внешне в ресурсах, чтобы не пересобирать проект каждый раз, когда потребуется поправить правописание. Ну и чтобы переводчики могли независимо от программистов работать.
                                      А если это внутренние строки для логирования и прочей питушни, то только ASCII, только хардкор.
                                      Ответить
                                  • Бывает багор гораздо проще. Мне встречалась гитуха, где кто-то взял и зачекинил BOM во все файлы, а древний копулятор с этого усрался.
                                    Ответить
                                    • PHP, емнип, из-за BOM преждевременно отправлял заголовки и ломалась установка кук и т.п.
                                      Ответить
        • >указывает на первый элемент массива
          > указывает на сам массив

          в сишке это одно и тоже: указатель на первый элемент равен указателю на сам массив
          имено потому массивы с ноля
          Ответить
          • Типы немного отличаются для sizeof(...) и т.п.
            Ответить
            • Попробуй муа-муа
              Попробуй джага-джага
              Ответить
            • а еще отличается выделение место, да)

              я имел ввиду что в данном случае нет разницы, а между

              petuh* a;
              и
              petuh a[22]

              конечяно е
              Ответить
          • Попробуй int (*a_p3)[4] = a
            Ответить
            • не сокмпилица же
              как я могу массив в указатель скопировать?
              Ответить
              • Можешь, это всего лишь предупреждение... Массив неявно превратится в указатель на элемент, поэтом неявно превратится указатель на массив...
                Ответить
                • какой пиздец)

                  я думал, компилятор когда справа массив видит, сразу нахуй посылает, если ты явно не кастанул
                  Ответить
                  • Когда вызываешь функции в духе void f(int* p), массив туда на ура заходит, даже без предупреждений.
                    Ответить
                    • так тож не справа

                      А про массив заходящий я знаю.
                      Ебадад потом делает ему sizeof() и итерируется, и всё работает годами, потому что размер массива оказался развен размеру указателя
                      Ответить
                      • Да можно и справа: int* p = a;
                        Ответить
                        • ну вот я не знал, что можно без каста.

                          Кстати, это забавный момент, когда "&a" равно "a"
                          Ответить
                          • А вот &a туда не лезет.

                            Буква L в названии языка C означает Logic.
                            Ответить
              • Простым присваиванием никак

                С помошью мемсру если моссив маленький или указатель достаточно разработан.
                Ответить
      • поскольку это указатель, то разницы нет

        в данном случае нет разницы указатель на инт или указатель на массив интов, если ты ождиаешь четыре инта
        Ответить

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