1. C++ / Говнокод #26040

    0

    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
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    #include <iostream>
    using namespace std;
    
    struct Rooster {
       int id = 0;
    };
    
    
    void asshole(const Rooster* roosters) {
        Rooster* r = (Rooster*)roosters;
        for (int i = 0; i < 3; i++) {
            r[i].id = i + 1;
        }
    }
    
    
    int main() {
    	Rooster roosters[3];
        asshole(roosters);
        for (int i = 0; i < 3; i++) {
            printf("%d\n", roosters[i].id);
        }
    	return 0;
    }

    https://ideone.com/Xk9Ukg

    Нахуй так жить?

    Запостил: BJlADuMuPCKuu_nemyx, 22 Ноября 2019

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

    • Теье не нра что конпелятор молча разрешает снять comst?
      Ответить
    • Даже с ключом -Стена ни одного ворнинга.
      Ответить
    • показать все, что скрытоvanished
      Ответить
      • Я должен был использовать злоебучий "static_cast<>"? Нахуй он нужен, если скобочки короче?
        И вообще, представь, что "asshole" писал не я. Я просто передал в функцию const.
        Ответить
        • показать все, что скрытоvanished
          Ответить
          • > зачем он принял const, и изменил его?
            это из разряда #define true false и т.п.
            Ответить
            • показать все, что скрытоvanished
              Ответить
              • Перевёл на «plain C»:
                #include <stdio.h>
                
                typedef struct Rooster_tag {
                   int id;
                } Rooster;
                
                
                void asshole(const Rooster* roosters) {
                    Rooster* r = roosters;
                    for (int i = 0; i < 3; i++) {
                        r[i].id = i + 1;
                    }
                }
                
                
                int main() {
                    Rooster roosters[3] = {{.id = 0}, {.id = 0}, {.id = 0}};
                    asshole(roosters);
                    for (int i = 0; i < 3; i++) {
                        printf("%d\n", roosters[i].id);
                    }
                	return 0;
                }


                https://ideone.com/v7XWm0

                Всего лишь ворнинг:
                a.c: In function 'asshole':
                a.c:9:18: warning: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
                     Rooster* r = roosters;
                                  ^~~~~~~~
                Ответить
                • показать все, что скрытоvanished
                  Ответить
                  • Привычка. Какие-то древние компиляторы ругались, когда структура безымянная, даже если следует тайпдеф.

                    Вот Dummy0001 (правильно написа́л его юзернейм?) любит повсюду писа́ть слово «struct». Вот ему Rooster_tag пригодится.

                    Перевёл на язык «Dummy0001»:
                    #include <stdio.h>
                    
                    struct Rooster_tag {
                       int id;
                    };
                    
                    
                    void asshole(const struct Rooster_tag* roosters) {
                        struct Rooster_tag* r = roosters;
                        for (int i = 0; i < 3; i++) {
                            r[i].id = i + 1;
                        }
                    }
                    
                    
                    int main() {
                        struct Rooster_tag roosters[3] = {{.id = 0}, {.id = 0}, {.id = 0}};
                        asshole(roosters);
                        for (int i = 0; i < 3; i++) {
                            printf("%d\n", roosters[i].id);
                        }
                    	return 0;
                    }

                    Ничего не забыл или надо ещё побольше слов «struct» напихать?
                    Ответить
                    • показать все, что скрытоvanished
                      Ответить
                      • Верните на «Говнокод» Dummy0001. С ним были такие интересные холивары! Он повсюду пытался доказать, что тайпдефы не нужны.
                        Ответить
                        • показать все, что скрытоvanished
                          Ответить
                          • показать все, что скрытоvanished
                            Ответить
                            • В сишке конст значит немного не то:
                              const int N = 100500;
                              Rooster roosters[N];
                              не сконпилица.
                              Ответить
                              • Именно поэтому я за «constexpr».
                                Ответить
                                • А в «C++20» обещают ещё «consteval»:
                                  https://en.cppreference.com/w/cpp/language/consteval

                                  Главное — не перепутать, где использовать «constexpr», а где «consteval»:
                                  consteval int sqr(int n) {
                                    return n*n;
                                  }
                                  constexpr int r = sqr(100);  // OK
                                   
                                  int x = 100;
                                  int r2 = sqr(x);  // Error: Call does not produce a constant
                                   
                                  consteval int sqrsqr(int n) {
                                    return sqr(sqr(n)); // Not a constant expression at this point, but OK
                                  }
                                   
                                  constexpr int dblsqr(int n) {
                                    return 2*sqr(n); // Error: Enclosing function is not consteval and sqr(n) is not a constant
                                  }

                                  Правда, простой и понятный язык?
                                  Ответить
                                  • показать все, что скрытоvanished
                                    Ответить
                                    • Точно.

                                      У них ещё и constinit есть:
                                      https://en.cppreference.com/w/cpp/language/constinit

                                      Это когда мы хотим убедиться, что начальное значение переменной является константой, чтобы оно попало в бинарник, но дальше мы значение переменной хотим изменять.
                                      Ответить
                                      • показать все, что скрытоvanished
                                        Ответить
                                        • Итак, если я правильно понял, constexpr разрешает использовать выражение в константном контексте, но не зашкваривает его. Мы это выражение можем использовать и в константном контексте (тогда оно вычисляется на этапе компиляции), и в неконстантном (тогда оно вычисляется в рантайме).

                                          Таким образом, constexpr ещё не гарантирует, что оно всегда будет константой. Это только хинт для компилятора, что тут можно оптимизировать.

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

                                          Если мы зашкварили функцию атрибутом consteval, то для того, чтобы такой же код использовать с переменным аргументом, его придётся продублировать (под другим именем).

                                          constinit же придумали для привередливых, которые хотят убедиться, что начальное значение будет посчитано на этапе компиляции и попадёт в секцию данных.

                                          Ничего не перепутал?
                                          Ответить
                                          • Сколько питушни нагородили! Получается уже 4 класса сущностей, куча времени на обучение тонкостей и боль при переводе функций из разряда обычных в какой-нибудь другой разряд.

                                            Сделали бы уже простую двухпроходную схему.
                                            1. Везде, где нужна константа времени компиляции, выражение заключается в вызов const
                                            2. При компиляции программа запускается, значения внутри const берутся из памяти и сохраняются для вставки в скомпилированную версию
                                            3. Для сложных кобенаций указателей сделать operator char* + constructor (char*) или отдельные операторы сериализации-десериализации (вообще, стандартные они бы пригодились и без этого). Компилятор может соптимизировать десериализатор, если что.

                                            Всё. Не нужно наворачивать говна, сильно усложнять компилятор и стандарт.
                                            Ответить
                                            • Все помнят, что само слово «const» в «C++» может использоваться не только в описании типа, но и в описании методов класса, где оно имеет особое значение?
                                              https://en.cppreference.com/w/cpp/language/member_functions#const-.2C_volatile-.2C_and_ref-qualified_member_functions

                                              int operator[](int idx) const {
                                                                        // this has type const Array*
                                                      return data[idx]; // transformed to (*this).data[idx];
                                                  }


                                              Кстати, что оно там означает?
                                              Ответить
                                              • Все, кто пишет на C++ что-то серьёзное, помнят.

                                                > Кстати, что оно там означает?
                                                Сам себе ответил же:
                                                > this has type const Array*
                                                Ответить
                                                • А ещё в C++ можно создать константный указатель на неконстантный указатель на константного питуха и неконстантный указатель на константный указатель на неконстантного питуха.
                                                  Ответить
                                                  • Как-то так должен начинаться рекламный ролик про typedef.
                                                    Ответить
                                                  • Настоящим царям для указателей вполне достаточно void *, char * и явных кастов во всякую другую хуйню
                                                    Ответить
                                                    • Действительно, const придумали для анскиллябр, которые сами себе не доверяют.
                                                      Ответить
                                              • показать все, что скрытоvanished
                                                Ответить
                                                • В «PHP» этого тоже нету. Именно поэтому я за «PHP».
                                                  Ответить
                                              • Основное назначение такого const — реализация иммутабельных методов, которые можно дёргать у константного объекта/ссылки:
                                                struct Kurochka {
                                                    void snestiYaichko()
                                                    {
                                                        yaichki--;
                                                        puts("Kok!\n");
                                                    }
                                                
                                                    void kukareknut() const
                                                    {
                                                        puts("Ja ne petuh, ya kuritsa!\n");
                                                    }
                                                
                                                    int yaichki = 10;
                                                };
                                                // ...
                                                const Kurochka kurochka{};
                                                kurochka.kukareknut();
                                                kurochka.snestiYaichko();  // error

                                                А ещё методы можно перегружать по константности:
                                                struct Kurochka {
                                                    void kukareknut()
                                                    {
                                                        yaichki--;
                                                        puts("*snesla yaichko ot vozmuscheniya*");
                                                    }
                                                
                                                    void kukareknut() const
                                                    {
                                                        puts("Ja ne petuh, ya kurochka!");
                                                    }
                                                
                                                    int yaichki = 10;
                                                };
                                                // ...
                                                Kurochka kurochkaMutable{};
                                                const Kurochka kurochkaImmutable{};
                                                kurochkaMutable.kukareknut();    // *snesla yaichko ot vozmuscheniya*
                                                kurochkaImmutable.kukareknut();  // Ja ne petuh, ya kurochka!

                                                Хороший пример использования такого подхода — реализация begin()/end() в итераторах. Это очень удобно тем, что не нужно беспокоиться о константности ссылки, «for (auto it = vec.begin();...)» сработает и для «T &», и для «const T &», причём во втором случае it будет константным итератором.

                                                Именно поэтому…
                                                Ответить
                                              • /del
                                                Ответить
                              • показать все, что скрытоvanished
                                Ответить
                                • "Используя данный паяльный флюс, не следует забывать о том, что это химикат и работа с ним требует соблюдения правил безопасности. Во время лужения следует беречь слизистые желудка и глаз. Работа осуществляется при помощи кисточки, которая прилагается к комплекту ЛТИ-120. В случае если паяльный флюс попал на кожу, пораженные участки следует промыть большим количеством воды с использованием мыла."
                                  Ответить
                                  • При работе ты дышишь. Всегда.
                                    Если пары жидкости растворимы, они осаждаются на слизистых и в дальнейшем проникают в слюну, которая может проглатываться, кроме того, всасывание происходит на всей поверхности пищеварительной трубки, начиная от полости рта и кончая в толстой кишкой.

                                    Именно поэтому работать с химикатами на голодный желудок гораздо опаснее, чем на сытый.
                                    Ответить
                              • показать все, что скрытоvanished
                                Ответить
                                • В сишке const — это не константа, а переменная, защищённая от изменения (смешно, да?). Вроде как оставили лазейку для того, чтобы в качестве начального значения можно было использовать произвольное выражение, а не только константу.

                                  Чтобы объявить обычный массив (не динамический!), в качестве его размера нужно задать чистую константу.
                                  Ответить
                                • #include <stdio.h>
                                  
                                  const int N = 100;
                                  int * huroz = &N;
                                  
                                  int main() {
                                      *huroz = 265;
                                      printf("%d\n", N);
                                      return 0;
                                  }


                                  Падает во время исполнения, потому что линкер поместил N в секцию .rdata. На платформе же без секции .rdata значение N будет подменено.
                                  Ответить
                                  • Надо быть полным додиком, чтобы править константу.


                                    Ответить
                        • показать все, что скрытоvanished
                          Ответить
                    • показать все, что скрытоvanished
                      Ответить
                      • Кстати, а в чем тут смысл униксого подхода?
                        Ответить
                    • ахахах, пустая ослиная нора)))
                      Ответить
                • показать все, что скрытоvanished
                  Ответить
                  • В крестах с таким же кастом тоже без ворнинга. Вообще тихо.

                    А вот без каста в крестах будет ошибка.
                    Ответить
                    • показать все, что скрытоvanished
                      Ответить
                      • Кстати, «PHP» не позволит в функцию передать по ссылке константу:
                        PHP Fatal error:  Only variables can be passed by reference
                        Ответить
                        • показать все, что скрытоvanished
                          Ответить
                          • А в «PHP» нет оператора бэкслэш. Там вообще нельзя брать адреса, можно только ссылки, но ссылки тупо являются синонимами. Зато во многих местах можно лазить по массиву всех переменных, всех констант, всех функций, всех классов.

                            <?php
                            
                            $a = 123;
                            
                            $$a = 12; // Эта строка создаст переменную с именем 123.
                            // Обратиться к ней как $123 будет нельзя, это синтаксическая ошибка.
                            // Но её видно в массиве глобальных переменных как $GLOBALS[123]
                            // и, внезапно, как ${123}. Да, фигурные скобки позволяют обращаться
                            // к некорректно названным переменным:
                            var_dump(${123});
                            Ответить
                            • показать все, что скрытоvanished
                              Ответить
                            • показать все, что скрытоvanished
                              Ответить
                              • показать все, что скрытоvanished
                                Ответить
                              • Где ты пистоне примитивы видел? Там одни объеткы и всё по ссылке (на обект) пиридается. Просто многие немутабельны и ещё нет ссылок именно на переменные (которые все хранят ссыки на объекты).
                                Ответить
                                • показать все, что скрытоvanished
                                  Ответить
                                  • Представь себе, а иначе зачем ещё хранить кеш маленьких чисел?

                                    Можешь посмотреть реализацию:
                                    https://github.com/python/cpython/blob/master/Objects/longobject.c
                                    Ответить
                                    • И правда, кеш малышей
                                      PyObject *v = (PyObject*)small_ints[ival + NSMALLNEGINTS];


                                      Видимо это сделано для единнообразности: работать с большими и маленькими числами удобнее одинаково, даже если мы и теряем немного времени на ненужной (с точки зрения байтойоба) операции, ведь мощность указательного типа на современных архитектурах может превышать мощность типа, необходимого для хранения небольших чисел.

                                      Кажется, в Ruby раньше для больших и малых чисел использовались разные типы (с автоматическим превращением, разумеется), но возможно что это уже не так.
                                      Ответить
                                      • А его можно испортить, как в «Жабе», чтобы 2+2 равнялось пяти?
                                        Ответить
                                        • Никогда не пробовал портить ничего в питоне.

                                          Приятнее всего портить что-то в Ruby, там для этого есть все возможности
                                          class Fixnum 
                                              def +(obj) 
                                                  42 
                                              end
                                          end
                                          
                                          p 2 + 2 # 42


                                          В Perl так же присутствуют мощные инструменты для портинья
                                          use overload;
                                          BEGIN {
                                          	sub foo {
                                          		42;
                                          	}
                                          	overload::constant ( integer => \&foo);
                                          }
                                          
                                          print 2 + 2; # 84
                                          Ответить
                                        • Не знаю, ссылки на кеш из питана вроде нет, но можно получить адресс обеъекта (id() это вроде он и есть). Только вот в питоне я умею только читать по адресу в памяти, а писать не умею. В питоне всё это онально огорожено.
                                          Ответить
                              • Учитывая, что C это по сути подмножество ObjC, я не понимаю, что ты имел в виду, когда их противопоставлял.
                                Ответить
                                • показать все, что скрытоvanished
                                  Ответить
                                  • Я прост не понял, почему мы сравниваем с С/C++. Имеет смысл сначала сравнить как раз сами C и C++ между собой.

                                    Про объекты в Obj C ты правильно пишешь, но вот остальные типы данных там один в один сишные и ведут себя ЕМНИП как сишные. Думаю, что структуры сишные в Obj C методы тоже можно передавать всеми известными способами, но проверять лень

                                    В этом смысле Свифт другой: там есть чёткое разделение на value и reference прямо на уровне языка. Как по мне, то в прикладухе такая ясная семантика важнее, чем некая условная гибкость
                                    Ответить
                                    • Мне тоже кажется, что обычные сишные сущности (structы и скалярные типы) работают в ObjC так же, как и в си.

                                      Вероятно, речь тут о том, что в С и С++ программист сам решает, как ему передавать объект: может скопировать, а может передать ссылку или указатель, причем передавать указатель можно даже для объекта на стеке (и разумеется всегда для объекта на куче, так как доступа к нему кроме как через указатель нет).
                                      Речь конечно о ситуации, когда программист имеет контроль и над вызываемой функцией тоже.

                                      ObjCные же объекты всегда располагаются на куче (кроме блоков, кажется, но и те копируются при передаче наружу) и у программиста нету выбора где из создать (и, соответственно, как их передать).

                                      Разделение на value и reference мне нравится.
                                      А можно передать по ссылке value object?

                                      Я спрашиваю, потому что например в C# можно (хотя по умолчанию он конечно скопируется) а например в Java -- нельзя
                                      Ответить
                                      • > А можно передать по ссылке value object?
                                        - формально да. Фактически происходит двойное копирование.

                                        https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID545

                                        Но, честно говоря, не помню даже, когда бы писал функции с inout
                                        Ответить
                          • Где здесь use constant?
                            Ответить
                  • показать все, что скрытоvanished
                    Ответить
                • > Всего лишь ворнинг
                  Именно поэтому я за "-pedantic-errors".
                  Ответить
          • А зачем конпилер даёт это сделать?
            Ответить
            • кууик
              нууу
              эээ
              ммм

              Это же си, чувак. Тут можно сделать всё, что угодно.
              Ты можешь взять число 1234 и скастить его в указатель на массив интов, и что-то там поправить по этому адресу с известными последствиями.

              Хочешь, чтоб такое вообще не компилировалось?
              Ответить
          • >> скобочки имеют мутную семантику

            Так точно. Список того, что делают скобочки, очень длинный, и в уме это просчитать трудно, обязательно какой-нибудь из вариантов упустишь из виду. В крестах лучше более явные касты.
            Ответить
            • Скобочки — это «оператор javascript». Скасти что угодно во что угодно* и получи какую-нибудь хуйню. Может быть даже она будет полезна.
              *почти
              Ответить
              • С новым годом тоскливый родной Бессмертный одинокий умный злой преданный изобретательный больной счастливый говнокод.
                Ответить
          • for (int i = 0; i < (int) roosters.size(); i++)

            Имею привычку не использовать «unsigned» при итерации.
            Также имею привычку при сравнении «unsigned» и «int» приводить к «int».
            Ответить
            • показать все, что скрытоvanished
              Ответить
            • С тех пор, как поглядел на интовые багры — имею привычку вообще никогда не использовать знаковые типы, за исключением случаев, когда требуется обработать отрицательное число.
              И я за «size_t».
              Ответить
              • for (i = size - 1; i >= 0; i--)


                Выкуси.
                Ответить
                • Не нужен.
                  const char *str = "Hello";
                  size_t size = strlen(str);
                  while (size--) {
                      putchar(str[size]);
                  }  // olleH

                  std::string str = "Hello";
                  for (auto it = str.rbegin(); it != str.rend(); ++it) {
                      std::cout << *it;
                  }  // olleH
                  Ответить
    • показать все, что скрытоvanished
      Ответить
      • Предположу, что компилятор по другому соптимизировал, и выкинул нахуй вызов asshole, и остались нули. Сейчас запущу...
        Ответить
        • показать все, что скрытоvanished
          Ответить
          • Именно поэтому я за реальный режим.
            Ответить
            • показать все, что скрытоvanished
              Ответить
            • Рустер, ты пробовал писать свою ОС проги, которые выполняются без ОС?
              Ответить
              • показать все, что скрытоvanished
                Ответить
                • На чём писал, кстати? На ассемблере, в мышиных котах или на ЯВУ?
                  Ответить
                • Я как-то пытался уместить форт-системку в бут-сектор, но когда она стала способна исполнять введённый код она уже даже в 2 сектора не умещалась (((

                  Это было года 3-4 назад, я только учил асм, сейчас тот код мне кажется глупым. Может быть если использовать байт-код и вынести заголовки отдельно и уместится, но я стал гораздо более ленивее.

                  Кстати, я тогда не ладил с родителями и мне не разрешали садится за комп, я написал эту системку на смартфоне и собирал и отлаживал её также на смарте в досбоксе )))
                  Ответить
                  • Кококококой хардкор )))
                    Ответить
                  • У меня где-то 8кб получалось на базовую систему на 32-битном асме. Жаль, что код куда-то проебался.
                    Ответить
                    • показать все, что скрытоvanished
                      Ответить
                    • Standalone под x86? Наверное неплохо.

                      Кстати об ОС и маленьких программах, когда-то на форуме фасма проводилась специальная олимпиада на 512-батную ОС, в посылках были всякие аналоноги досовских дебагеров и тетрисы, а первое место заняла многозадачная Nano OS да ещё и с тремя демо-приложениями для теста.

                      Тут есть архив с посылками:
                      http://board.flatassembler.net/topic.php?t=2164&postdays=0&postorder=as c&start=140

                      Чувствую себя анскилляброй(
                      Ответить
                      • 78 килобайт. Не мега и не гига. Архив из 12 операционок. Какой скилл )))
                        Ответить
                        • Причём с сорцами. И в сорцах ничего необычного нет, ждешь увидеть там кучи всяких хаков, повторное использование цепочек кода, полиморфный код и т.п., а там самый обычный ассемблерный подпрограммный код. Я даже немного разочаровался.
                          Ответить
                          • показать все, что скрытоvanished
                            Ответить
                            • Потому что в node_modules один и тот же фрагмент кода повторяется 100500 раз, ибо NIH.
                              Ответить
                            • Посмотрим, чем забит npm:
                              https://www.npmjs.com/package/is_number
                              https://www.npmjs.com/package/@nathanfaucett/is_number
                              https://www.npmjs.com/package/@jwaterfaucett/is_number

                              Три пакета, определяющие, является ли аргумент числом.

                              https://www.npmjs.com/package/is_string
                              https://www.npmjs.com/package/@indlekofer/is_string
                              https://www.npmjs.com/package/@jwaterfaucett/is_string

                              Три пакета, определяющие, является ли аргумент строкой.

                              https://www.npmjs.com/package/is_boolean
                              https://www.npmjs.com/package/is_finite
                              https://www.npmjs.com/package/is_null
                              https://www.npmjs.com/package/is_object
                              https://www.npmjs.com/package/is_empty
                              https://www.npmjs.com/package/is_undefined
                              https://www.npmjs.com/package/is_nan

                              Тоже очень нужные пакеты.
                              Ответить
                              • показать все, что скрытоvanished
                                Ответить
                                • Вот весь код устанавливаемого модуля:
                                  module.exports = isNull;
                                  
                                  
                                  function isNull(value) {
                                      return value === null;
                                  }


                                  К нему прилагаются юнит-тесты, метаданные пакета, Gruntfile.js, .travis.yml и ещё какая-то поебень.
                                  Ответить
                                  • показать все, что скрытоvanished
                                    Ответить
                                    • У тебя опечатка. Выпустил патч для твоего модуля:
                                      -     return value === isSergievPosad;
                                      +     return value === "Сергиев Посад";
                                      Ответить
                                      • показать все, что скрытоvanished
                                        Ответить
                                        • var tape = require("tape"),
                                              isSergievPosad = require("../src/index");
                                          
                                          
                                          tape("isSergievPosad(value) should return true when the value is a Сергиев Посад", function(assert) {
                                              assert.equal(isSergievPosad(undefined), false);
                                              assert.equal(isSergievPosad({}), false);
                                              assert.equal(isSergievPosad([]), false);
                                              assert.equal(isSergievPosad(""), false);
                                              assert.equal(isSergievPosad(/./), false);
                                              assert.equal(isSergievPosad(0), false);
                                              assert.equal(isSergievPosad(null), false);
                                              assert.equal(isSergievPosad(function noop() {}), false);
                                          
                                              assert.equal(isSergievPosad("Cергиев Посад"), true);
                                          
                                              assert.end();
                                          });
                                          Ответить
                                • Хейтер жс плюсанул. Так и рождаются предрассудки. JS - не большее говно, чем C++. Но есть отличие: с C++ надо настолько долго пердолиться, чтобы что-то внятное написать, что в мире C++ есть либо те, кто ещё не знает этот язык и не может о нём судить, либо те, кто провёл с ним столько времени, что его мозг свыкся с происходящим и уже получает удовольствие. JS же прост и понятен, ему не посвящается столько времени, не формируется синдром утёнка.

                                  NPM работает на пользу Node.js, где есть своя удобная стандартная библиотека https://nodejs.org/api/ с прекрасной документацией.

                                  А большое количество мусорных пакетов говорит юношеском максимализме аудитории, не более того. Понятия модульности и переиспользования возводятся в абсолют.
                                  Ответить
                                  • показать все, что скрытоvanished
                                    Ответить
                                    • Да, это верно.

                                      Хотя, дураки в сообществе - это наоборот хороший знак. Язык достаточно удачен, чтобы на нём смог писать даже идиот.

                                      Это только люди, у которых программирование съело мозг, формируют взгляды на него как на занятие отборной элиты, где не должно быть ни дураков, ни представителей каких-то других профессий, кроме божественных программистов. Но снаружи этого манямирка в реальном мире находятся люди, которым нужна автоматизация их задач, и которым насрать, как там передаётся значение, по ссылке или нет, кто им будет владеть и чем виртуальный метод отличается от невиртуального. Главное - чтобы программа работала, приносила доход и для её обслуживания не надо было нанимать докторов хаскельных наук.
                                      Ответить
                                  • показать все, что скрытоvanished
                                    Ответить
                                    • Если не использовать "prototype" и "this". C++ тоже прост и понятен, если не использовать метушню.
                                      Ответить
                                      • В «PHP» нет ни «ргототуре», ни «метушни». Именно поэтому я за «PHP».
                                        Ответить
                                    • Ну, он в первом прав.
                                      На самом деле JS прост и ебанут.
                                      Ответить
                      • показать все, что скрытоvanished
                        Ответить
                  • показать все, что скрытоvanished
                    Ответить
              • Форт считается за ОС?
                Ответить
          • "Ошибка выполнения"
            https://ideone.com/1jkccD
            Ответить
      • UB. Откастить конст у ссылки можно, но если объект, на которую она указывает, объявлен константным — при попытке доступа будет пиздец.
        А вот если объект мутабельный — всё будет окей. Именно поэтому я за «C(++)».
        Ответить
    • А теперь посмотрим, как сделали в других ЯП.

      В Паскале модификатор const параметра функции принимает аргумент по ссылке, но запрещает явное изменение значения внутри функции. Да, ссылка — это синтаксический сахар, когда фактически передаётся указатель (без копирования данных), но выглядит, как будто передали данные. Проверяем:
      type
        Rooster = record
         id: integer;
        end;
        RoosterArray = array[0..2] of Rooster;
      
      procedure asshole(const roosters: array of Rooster);
        var
          r: ^RoosterArray;
          i: integer;
        begin
          r := @roosters;
          for i := 0 to 2 do r^[i].id := i + 1
        end;
      
      var
        roosters: RoosterArray;
        i: integer;
      begin
        for i := 0 to 2 do roosters[i].id := 0;
        asshole(roosters);
        for i := 0 to 2 do Writeln(roosters[i].id)
      end.


      https://ideone.com/SWpK67

      Да, работает так же, как в сишке/крестах. Компилятор явно запретил внутри процедуры изменять значение roosters, но не запретил брать адрес и модифицировать косвенно. Какой багор )))
      Ответить
      • Модифицируем: объявим в глобальном контексте roosters не как переменную, а как типизированную константу:
        type
          Rooster = record
           id: integer;
          end;
          RoosterArray = array[0..2] of Rooster;
        
        procedure asshole(const roosters: array of Rooster);
          var
            r: ^RoosterArray;
            i: integer;
          begin
            r := @roosters;
            for i := 0 to 2 do r^[i].id := i + 1
          end;
        
        const
          roosters: RoosterArray = ((id: 0), (id: 0), (id: 0));
        var
          i: integer;
        begin
          asshole(roosters);
          for i := 0 to 2 do Writeln(roosters[i].id)
        end.


        Компилируем, запускаем... Ничего не изменилось. Оказывается, в «Турбо Паскале» тупизированные константы (в отличие от нетупизированных) на самом деле являются инициализированными переменными. Отключаем совместимость с «Турбо Паскалем» директивой {$J-}. Компилируем, запускаем... В «Windows» падает от нарушения защиты, потому что компилятор поместил константу в секцию .rdata, закрытую от записи.

        В «Ideone» же защита не сработала: https://ideone.com/pvoMYf
        Видимо, та модификация компилятора, которая установлена в «Ideone», ридонли-секцию не создаёт.
        Ответить
        • показать все, что скрытоvanished
          Ответить
          • * Вариантные записи — за пределами Standard Pascal (который я не проверял) не проверяются. Из-за отсутствия проверки их повсеместно используют не по назначению, как сишный union, а именно для эмуляции reinterpret_cast. Добавлять проверку уже поздно, потому что куча софта сломается.

            * Чтобы наебать ренджи, нужно компилировать с директивой $R-.

            * const:
            1. В параметре функции — да, легко наёбывается взятием указателя. Напрямую модифицировать компилятор всё-таки не даёт (уже на этапе компиляции запрещает присвоение).
            2. Как типизированная константа — пофиксили во Фрипаскале, если при компиляции отключить совместимость с Турбопаскалем.
            Ответить
          • К слову, в Delphi изобрели тип Variant:
            https://freepascal.org/docs-html/current/ref/refsu18.html

            Для него рантайм проверяет, значение какого типа в данный момент хранится. К сожалению, он может хранить значения только из фиксированного набора типов (скалярные, включая плавающих питухов и перечисления, строки, указатели).
            Ответить
            • показать все, что скрытоvanished
              Ответить
              • Как я понял, Variant создавали ради возможности работы с OLE-OLE-OLE-OLE, точнее, с COM. Лень искать борландовскую документацию, но во Фрипаскале можно так:
                https://freepascal.org/docs-html/current/ref/refsu20.html

                Var  
                  W : Variant;  
                  V : String;  
                 
                begin  
                  W:=CreateOleObject('Word.Application');  
                  V:=W.Application.Version;  
                  Writeln('Installed version of MS Word is : ',V);  
                end;


                А вот это уже не по-паскалевски, ибо статический анализатор для строчки V:=W.Application.Version; не работает. Это синтаксический сахар: она трансформируется в вызов API, которому передаётся строка 'Application.Version'.
                Ответить
          • > * есть вариантные записи, но их можно наебать

            Оказывается, «Irie Pascal» строго проверяет вариантные записи. Остальные реализации — да, можно наебать.
            Ответить
        • показать все, что скрытоvanished
          Ответить
          • Я бы их скопировал, если бы там было так:
            procedure asshole(roosters: array of Rooster);


            А у меня слово «const». Оно отменяет копирование (как «var»), но при этом компилятор включает статический анализатор кода, запрещающий изменение значения.
            Ответить
            • показать все, что скрытоvanished
              Ответить
              • Это в документации. Если не ошибаюсь, расширение языка, придуманное Борландом, в Standard Pascal такого не было.
                Ответить
                • показать все, что скрытоvanished
                  Ответить
                  • Точно были нетипизированные константы, потому что препроцессора с дефайнами у Паскаля не было. В ИСО 7185 нетипизированные константы есть:
                    http://www.pascal-central.com/docs/iso7185.pdf
                    Да, секция, открывающаяся словом const.

                    Типизированных констант в этом документе не нашёл, как и параметров-констант у функций.
                    Ответить
                    • показать все, что скрытоvanished
                      Ответить
                      • В TP в секции const ещё можно было указывать типизированные: у них сразу за идентификатором перед равенством указывался тип (отделялся от идентификатора двоеточием). Обычно типизированные использовались для нескалярных типов.

                        Так вот реализация в TP имела даже не дыру, а парадные ворота: типизированные константы не были защищены от изменения. По факту это были переменные с начальным значением (они помещались в инициализированную часть секции, физически присутствующую в экзешнике, в отличие от переменных из секции var, которые были в той части, которая физически в экзешнике не присутствовала и создавалась во время загрузки).

                        Во Фрипаскале это пофиксили: там сделали возможность у var указывать начальное значение, а типизированные константы защитили от изменения. Но при этом добавили переключатель, включающий режим обратной совместимости.
                        Ответить
                        • показать все, что скрытоvanished
                          Ответить
                        • показать все, что скрытоvanished
                          Ответить
                          • А как это работало и в каком компиляторе?

                            В TP, начиная с 4.0, не скомпилируется, потому что слово IMPLEMENTATION зарезервировали для модулей.
                            Ответить
                          • Честно проверил BP 7.0, TP 6.0, TP 5.5, TP 4.0 и даже Microsoft Quick Pascal 1.0 (это первая и последняя версия «Паскаля» в реализации «Микрософта», по сути пародия на TP 4.0). Во всех компилятор сообщает, что implementation — зарезервированное слово. Это не противоречит хелпу.

                            Это слово — расширение языка, придуманное «Борландом» в версии 4.0, когда добавили модульную систему.

                            Что не так?
                            Ответить
                            • Можно я попробую:

                              Мне тут говорили, что в стандартном паскале модульцев не было, поэтому прога использующая идентификатор interface работала в стандартном и обсирается в турбированном и его последователях?

                              Я угандал?
                              Ответить
                              • То есть нарушили обратную совместимось.
                                Ответить
                                • Именно так. В TP 3.0 и в более старых такой код компилировался, поскольку слова interface и implementation не были зарезервированы.

                                  По той же самой причине сишный код, содержащий переменные с именем «class», нельзя скомпилировать в «C++».
                                  Ответить
          • 1. Как у тебя: выводит 1.

            2. Добавим var — вернёт 20.
            procedure Foo(var bar: array of integer);


            3. Добавим const:
            procedure Foo(const bar: array of integer);

            Не компилируется:
            c2.pas(3,1) Error: Can't assign values to const variable
            Ответить
            • показать все, что скрытоvanished
              Ответить
              • Сейчас fpc, но могу и в tp проверить.

                Это константный указатель на питуха. Запрещено менять указатель, но не питуха.
                Ответить
                • показать все, что скрытоvanished
                  Ответить
                  • Честно? Не знаю. Боюсь, что в Паскале все указатели разрешают изменение разыменованных данных.
                    Ответить
                    • показать все, что скрытоvanished
                      Ответить
                      • Сишка и Паскаль развивались в разных направлениях.

                        В Си массив — это сахар над указателем. В Си модно было писать while(*p++ = *q++) и вообще использовать арифметику указателей, где только можно. Поэтому и задумались о защите объектов, на которые ссылаются указатели.

                        В Паскале же арифметики указателей нет. Можно, конечно, кастовать указатель в число, изменить и кастовать обратно в указатель. Можно использовать инкремент/декремент. Но так обычно не делают. В Паскале модно объявлять типы и делать всё через типы: массивы, записи и т. п. Заодно получим проверку границ индекса массива (которую в Си нужно делать вручную).

                        Возможно, по этой причине разработчики Паскаля (Вирт и разработчики более поздних реализаций) сразу об указателях на константного питуха не задумались.
                        Ответить
      • показать все, что скрытоvanished
        Ответить
    • А в C# некоторые новые служебные слова (например, относящиеся к Linq) работают только в контексте, а так могут быть использованы как имена переменных и т.п.:
      int[] from = { -1, 0, 1 };
      int select = (from v in @from where v > 0 select 2*v).First();
      Console.WriteLine(select); // 2

      (@ перед from нужна как раз чтобы показать, что это идентификатор, т.к. в данном контексте это уже зарезервированное слово)
      Ответить
      • Хорошо, что они оставили возможность явно использовать идентификатор в новом контексте (@).

        Говорят, в «PL/1» значков для отделения идентификаторов от ключевых слов не было. Такой код был валиден:
        IF IF = THEN THEN THEN = ELSE;
                     ELSE ELSE = IF;
        Ответить
      • Перевёл на «PHP»:
        <?php
        
        ${'function'} = [ -1, 0, 1 ];
        ${'reset'} = @reset(array_map(function($v){return 2*$v;}, array_filter(${'function'}, function($v){return $v>0;})));
        
        echo ${'reset'}, PHP_EOL;

        Собачка тут только для того, чтобы передать rvalue в функцию reset.
        Ответить

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