На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Редчайшая базовая конструкция языка Си (С89)
    Всем хай!

    Недавно столкнулся с таким объявлением:
    ExpandedWrap disabled
      int (*p)[10];


    Такого зверя вижу впервые! А вы?)
    Не стоит путать этого зверя с классическим одномерным массивом указателей, аля:
    ExpandedWrap disabled
      int *p[10]; // это одномерный массив, в котором каждый элемент - указатель на целое


    Как я понял, вот эта конструкция int (*p)[10] некая имитация двумерного массива.
    Но мне важнее понять другое: существует ли ситуация в коде на чистом Си (С89), когда без подобной конструкции НЕ ОБОЙТИСЬ???
      Массив указателей и указатель на массив.
        Цитата FasterHarder @
        Как я понял, вот эта конструкция int (*p)[10] некая имитация двумерного массива.

        Это указатель на массив. Вот тут (самое классное объяснение, что я когда-либо видел) объясняется, как читать и писать такие объявления.
          указатель на массив
          хм...
          указатель НА массив
          ну, ок...

          хочется, конечно, порассуждать на эту тему, но пока ладно

          А вообще вычитал, что благодаря этой конструкции есть возможность из одномерного массива ВЫРАСТИТЬ многомерный массив)

          Но это редкая штуковина, если провести эксперимент и в гугле открыть 100 программок на Си, то с вероятностью 99%+ ни в одной из них не будет юзаться эта конструкция...
            Цитата FasterHarder @
            А вообще вычитал, что благодаря этой конструкции есть возможность из одномерного массива ВЫРАСТИТЬ многомерный массив)

            Двузмерный массив можно получить вообще без всяких доп. конструкций a[i + j * w];
              Цитата FasterHarder @
              А вообще вычитал, что благодаря этой конструкции есть возможность из одномерного массива ВЫРАСТИТЬ многомерный массив)
              ExpandedWrap disabled
                int (*array)[10] = malloc(100 * sizeof(*array));        /* массив из 100 (колонки) массивов по 10 (строки) int-ов */
                int *line;
                 
                for (line = *array; line - array < 100; ++line)
                  /* перебираем массив построчно */;
                 
                free(array);
              Как-то так, наверное.
                Цитата Qraizer @
                Как-то так, наверное.

                абсолютно верно, маэстро!)

                вот скажи, Qraizer, только честно, тебе ХОТЬ РАЗ В ЖИЗНИ при написании программ на Си (а у тебя их за плечами по оценкам независимых экспертов свыше 25 000) пригодилась подобная конструкция???

                ну, вот эта:
                ExpandedWrap disabled
                  <тип данных> (*имя)[размер];
                  Указатель на массив? Было дело, в качестве параметра функции. А как тип свободной переменной пользовал ссылки на массивы. Но это Плюсы.

                  Добавлено
                  P.S. Указатели на массивы редко когда нужны просто. Были бы не Плюсы в тех задачах, пользовал бы указатели. Главная фишка тут даже не вариабельная длина первого измерения, а то, что не теряется длина второго измерения. Так что адресная арифметика на ++, -- и [] продолжает корректно работать. Если не забывать этот факт, найти применение сей конструкции можно и чаще.

                  Добавлено
                  P.P.S. Адресная арифметика на [] будет работать и на указателях на указатели, но там она только притворяется, что корректная. Как только понадобится передать такой int** в функцию параметром, тут же граблями по лбу.

                  Добавлено
                  Цитата OpenGL @
                  ...объясняется, как читать и писать такие объявления
                  Это ещё что. Мне вот как-то приспичило написать
                  ExpandedWrap disabled
                    const TypeInfo (&get()const)[Length<typename L::TypeList>::value];
                    /* ... */
                    ret_type (MD::*accepts[Length<typename CTL::Head::TypeList>::value])(param_type);
                  :blush:
                  Сообщение отредактировано: Qraizer -
                    Цитата Qraizer @
                    Это ещё что. Мне вот как-то приспичило написать

                    Qraizer, ну, вот зачем так сложно программировать!))

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

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

                    Твой код будет понятен только тебе) (ну, я утрирую, конечно, понятно, что не только тебе, но все же).
                    На форумах ооооооооооооооооочень часто может видеть сложнейшие конструкции. А НУЖНЫ ЛИ ОНИ?!!

                    зы: Макконел - признанный мировой авторитетнейший спец, с кучей наград и пр. пр. Поэтому отрицать его скилы бессмысленно...

                    я знаю, что тебе найдется, что мне ответить, доказав, что иногда без сложных конструкций никуда и им нет альтернативы. Но ты сам, как считаешь, ведь можешь писать код в разы проще и понятнее, чем делаешь это на практике в повседневной жизни (здесь и сейчас)?)
                      Чем больше сложных конструкций и использованных фреймворков, тем круче программист, тем больше денег он заслуживает.
                        Цитата FasterHarder @
                        Маконел в своей шедевральной книге приводит такую фразу (я ее запомнил, наверное, на всю жизнь): правильно написанный код может быть понятен даже человеку, которые вообще не знаком с программированием. ИМХО, это гениальнейшая фраза, как впрочем любой абзац его книги...
                        За любой абзац не скажу, не вижу их. Этот абзац... мягко говоря, не соответствует действительно от слова совсем. Уверен, его перевели с искажением смысла. "Правильность" кода определяется чётким формальным критерием: он решает ровно ту задачу, которую призван. Форма его представления вообще ничего не решает в этом смысле.

                        Добавлено
                        Цитата FasterHarder @
                        Но ты сам, как считаешь, ведь можешь писать код в разы проще и понятнее, чем делаешь это на практике в повседневной жизни (здесь и сейчас)?)
                        Иногда можно. Только зачем? Когда общаются специалисты в своей области, странно ожидать, что они будут использовать научно-популярный подход к выражению своих мыслей вместо специализированного рабочего формата. И это не неуважение в окружающим, им так банально проще и быстрее.

                        Добавлено
                        ExpandedWrap disabled
                          const TypeInfo (&get()const)[Length<typename L::TypeList>::value];
                        Тут мне понадобился константный метод класса, возвращающий ссылку на константный массив известной длины. Как я это напишу проще? Длина определяется метафункцией Length<> над параметром, переданным извне, и вычисляется при компиляции. Она и обязана вычисляться при компиляции, иначе будет бесполезна.
                        ExpandedWrap disabled
                          ret_type (MD::*accepts[Length<typename CTL::Head::TypeList>::value])(param_type);
                        Это массив указателей на методы класса MD, принимающие param_type и возвращающие ret_type. Тоже известно длины и тоже вычисляемой по параметру извне. Как это написать проще?
                        ExpandedWrap disabled
                          constexpr HierarchyDeep = Length<typename CTL::Head::TypeList>::value;
                          typedef ret_type (MD::*MethodsPtr)(param_type);
                          MethodsPtr accepts[HierarchyDeep];
                        Так что ли? Очень сомнительное упрощение. Теряется наглядность, определение сущности искусственно размазано по трём субъектам. Прочитать сложнее, т.к. приходится обратно восстанавливать ассоциативные связи между субъектами, делающими их единой сущностью. В перспективе от засилья новых субъектов кода быстро съедет крыша, а используются они однократно, ошибиться и заюзать не того субъекта не в том месте легче лёгкого. Ну и послушать если тех, кто воспользовался советами упрощать код, разбивая сложные определения на составные части, то они в один голос подтверждают, что да, понять определение зачастую легче, однако профит моментально уходит в плинтус, когда приходится постоянно дёргать экран туда-сюда, чтобы хренадцатый раз вспомнить, что же чьёртпобьери обозначает этот субъект, потому что держать в голове десяток почти не отличимых имён нереально та и нет желания.
                        Нет, FasterHarder, код не обязан быть простым, чтобы быть правильным. Он должен быть красивым, это лишний раз подтвердит класс его автора. Говорить красиво – это искусство, а мямлить если, отношение будет не то. Говорить умеют все, но ораторов среди нас значительно меньше. А писателей так вообще единицы.
                        Красота кода в его чёткости и лаконичности, а его понимание стоится вокруг качества его документирования. И это тоже искусство.
                        Сообщение отредактировано: Qraizer -
                            Qraizer, ок.
                            Поставим в диалоге многоточие)

                            Буду писать с приведением русскоязычного + англ.варианта цитат Макконелла - так будет проще разбираться. Мне даже самому интересно посмотреть, как ты будешь относиться к его философии культуры кода...Об этом вся его книга (под косарь страниц)

                            зы: и сразу хочу отметить такой факт: что у меня нет ни единого грамма желания СПОРИТЬ с тобой, что-то доказывать и пр. Это будет смешно! Ты супер спец в С/C++, знающий тонкости стандарта, поэтому можно сказать, что мы просто рассуждаем)
                              Цитата Qraizer @
                              Цитата FasterHarder @
                              Маконел в своей шедевральной книге приводит такую фразу (я ее запомнил, наверное, на всю жизнь): правильно написанный код может быть понятен даже человеку, которые вообще не знаком с программированием. ИМХО, это гениальнейшая фраза, как впрочем любой абзац его книги...
                              За любой абзац не скажу, не вижу их. Этот абзац... мягко говоря, не соответствует действительно от слова совсем. Уверен, его перевели с искажением смысла. "Правильность" кода определяется чётким формальным критерием: он решает ровно ту задачу, которую призван. Форма его представления вообще ничего не решает в этом смысле.

                              Добавлено
                              Цитата FasterHarder @
                              Но ты сам, как считаешь, ведь можешь писать код в разы проще и понятнее, чем делаешь это на практике в повседневной жизни (здесь и сейчас)?)

                              Всё правильно написано в книге. Хороший код понимается кем угодно, является самодокументируемым, то есть не нуждается в комментариях. Вы уволитесь, что будут делать Ваши преемники, переписывать программу с нуля?
                              Ваш код понятен только человеку, не только отлично знающему С++, но и хорошо знакомому с программой в целом. Подозреваю, что Вы единственный человек, который понимает что там написано.
                              Сообщение отредактировано: scrambrella -
                                Цитата scrambrella @
                                Хороший код понимается кем угодно, является самодокументируемым, то есть не нуждается в комментариях.
                                Не надоело мифы от пыли отряхивать? Где ты видел прожакшн без документации? Ну-ка, что тут происходит?
                                ExpandedWrap disabled
                                  float WTF(float number)
                                  {  
                                    float x2 = number * 0.5F;
                                    float halfedthree = 1.5F;
                                   
                                    union
                                    {
                                      float f;
                                      uint32_t i;
                                    } conv = {number}; // set 'conv::f' to 'number'
                                   
                                    conv.i = 0x5f3759df - ( conv.i >> 1 );
                                    conv.f*= halfedthree - x2 * conv.f * conv.f;
                                    
                                    return conv.f;
                                  }
                                Код из движка очень известной и нашумевшей в своё время игры. Если узнаешь, какой, то сам поймёшь, какую фигню сморозил.
                                Цитата scrambrella @
                                Подозреваю, что Вы единственный человек, который понимает что там написано.
                                Ну как, распознал ту WTF()? Если кто не умеет или не хочет читать, это его проблема. Мой код задокументирован. Комментарии поясняют реализацию, описание архитектуры идёт отдельно. Мои те две строки взяты с гитхаба, описание архитектуры есть у нас на форуме, ссылки на темы тоже на гитхабе.
                                  WTF - явно не хороший код.
                                  Для понимания нужно знание внутреннего представления float, на которое большинству программистов глубоко плевать.
                                    Тема хоть уже с поросла мхом, но уж звиняйте, только заметил.

                                    Цитата Qraizer @
                                    у как, распознал ту WTF()?

                                    Старый-добрый способ быстрого получения обратного корня. Не?

                                    А вот конструкция вида:
                                    ExpandedWrap disabled
                                      const TypeInfo (&get()const)[Length<typename L::TypeList>::value];
                                    меня, старого сишника, вводит в ступор :D
                                    Впрочем, плюсы знаю только в базовой версии и все эти тайпкасты меня обошли стороной, о чем ни разу и не пожалел.

                                    Вообще же в Си конечно перемудрили с разнообразием объявлений данных, можно было попроще. Предпочитаю использовать только два вида указателей:
                                    ExpandedWrap disabled
                                      int *p;
                                      int **p;
                                    Их хватает для любых задач. Остальное - комментарии пояснят, они для того и придуманы.
                                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                    0 пользователей:


                                    Рейтинг@Mail.ru
                                    [ Script execution time: 0,0737 ]   [ 17 queries used ]   [ Generated: 25.04.24, 01:22 GMT ]