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

    Комментарии (48) 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;
      означают одну и ту же хуйню? Или есть какая-то разница?
      Ответить
      • может совпало так.. а может это в контролерах только
        Ответить
        • А ты пойди проверь в вижуалстудии на венде у себя
          https://wandbox.org/permlink/Bi3wM2Jl2ZmhXzEZ
          Ответить
        • Конпеляторопейсатель не знает мосивы в Си.

          Это охуенно
          Ответить
      • 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 написать все равно нельзя. Может ли омниидемпотентность быть ограниченной?
              Ответить
        • >указывает на первый элемент массива
          > указывает на сам массив

          в сишке это одно и тоже: указатель на первый элемент равен указателю на сам массив
          имено потому массивы с ноля
          Ответить
          • Типы немного отличаются для 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.
                            Ответить
              • Простым присваиванием никак

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

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

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