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

    +118

    1. 1
    ... *sizeof(uint32_t)

    Правильно. А то вдруг кто его переопределит.

    Запостил: 3.14159265, 22 Мая 2014

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

    • Надо было хардкодить размер? А вдруг кто-то на 64 бита портануть решит?
      Ответить
      • >А вдруг кто-то на 64 бита портануть решит?
        Действительно! И там случится оказия: размер uint32_t станет совсем другим!
        Ответить
        • Там uint32_t может внезапно превратиться в uint64_t
          Ответить
          • uint32_t - это тип, а не переменная
            Ответить
          • Не может. uint_fast32_t / uint_least32_t могут, а uint32_t разве что отказаться компилироваться, если платформа не сможет предоставить тип размером 32 бита.
            Ответить
            • >Не может. uint_fast32_t / uint_least32_t могут, а uint32_t разве что отказаться компилироваться
              Ну разве что кто-то ручками переопределит #define uint32_t uint64_t
              Например Тарас в старых студиях ёбнет typedef int int32_t; на селероне-то всё нормально...
              Ответить
          • >Там uint32_t может внезапно превратиться в uint64_t
            Лол, и как ты умудряешься выдумывать подобную пургу?
            Ответить
        • typedef my_data_type uint32_t; // поменяй на 64, когда припрет
          Ответить
        • не говно.

          при портировании можно в лоб искать 32бит типы и смотреть надо ли их в 64бита конвертить или нет.

          в случае сериализации/десереализации данных, это по моему опыту единственный работающий подход. иначе можно с легкостью сменой пары строк сломать протокол.
          Ответить
        • Может и 64 получиться:
          long uint32_t;
          size_t size = sizeof(uint32_t);
          Ответить
    • на самом деле это сделано как бы в году читаемости
      читаешь код и видишь, это не какая-то четверка, это размер в байтах, все понятно
      Ответить
      • >это сделано как бы в году читаемости
        А константы для кого придумали? Часто завожу просто для того чтоб код был понятней, ну и собрать числа-настройки в одном месте.
        И чтоб изменить потом размер не придется по коду лазить и менять десятки этих типов. Они ведь не раз и не джва так написали.
        Ответить
        • uint32_t автоматом тоже не меняется. Кстати, а sizeof(var) катит?
          Ответить
          • > Кстати, а sizeof(var) катит?
            Вполне.
            Ответить
          • sizeof (any_expression) катит
            Ответить
            • sizeof(void) // guess what?
              Ответить
              • Предположил, что единица, и оказался прав (gcc 4.8.2).
                А вообще интересно:
                struct A {};
                
                /// C
                sizeof(void) == 1
                sizeof(struct A) == 0
                
                /// C++
                sizeof(void) <- Compilation error
                sizeof(struct A) == 1
                Ответить
                • Физический вакуум – это кипящий океан флуктуирующих виртуальных образований, он однороден и изотропен.
                  Ответить
                • Наврал, в плюсах тоже sizeof(void) == 1, просто ворнинг в еррор превратился.
                  Ответить
                  • >просто ворнинг в еррор превратился.
                    По-моему, не по стандарту:
                    5.3.3/1 The sizeof operator shall not be applied to an expression that has function or incomplete type ...

                    А нолик для
                    struct A
                    {
                       int a[];
                    };
                    можно получить.
                    Ответить
                    • > можно получить.
                      В крестах - нельзя.

                      Во-первых там нельзя писать безразмерные массивы int a[] в структуре (9.2-8: When an array is used as the type of a nonstatic member all dimensions shall be specified.).

                      Во-вторых там нельзя юзать массив нулевого размера int a[0] (8.3.4-1: If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.).

                      В-третьих - даже sizeof() от пустой структуры вернет не менее 1 (5.3.3-2 The size of a most derived class shall be greater than zero).

                      То, что gcc без -pedantic не матерится на это - это гццпроблемы гццрасширение для совместимости с сишкой: warning: ISO C++ forbids zero-size array ‘a’
                      Ответить
                    • > По-моему, не по стандарту:
                      Все там по стандарту:
                      3.9.1-9: The void type is an incomplete type that cannot be completed.
                      5.3.3-1: The sizeof operator shall not be applied to an expression that has function or incomplete type
                      Ответить
                      • Так я о том же, void нельзя в sizeof подставлять, а нолик как пример гццизма для разнообразного вывода. А то у Романа только единички были для крестов.
                        Ответить
                      • спасибо за пояснения
                        Ответить
        • > А константы для кого придумали?
          Ну sizeof(uint32_t) - и есть константа.
          Ответить
        • > И чтоб изменить потом размер не придется по коду лазить и менять десятки этих типов
          typedef же, и менять придется только в одном месте.
          typedef int Foo;
          
          Foo x;
          write(fd, &x, sizeof(Foo));
          Ответить
        • Константы в Си? Быть может вы имели в виду дефайны?
          Ответить
        • "И чтоб изменить потом размер не придется по коду лазить и менять десятки этих типов."

          что не так уж и сложно.

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

          а глупым способом, когда у тебя все uint32_t или uint64_t, намного легче заметить что у какого то поля неправильный тип.
          Ответить
          • > если ты делаешь сетевой протокол
            Если протокол или формат хранения - да, согласен, там из-за совместимости хуй кто поменяет типы. Да даже если и поменяют - это будет новая версия, а старую придется какое-то время поддерживать (т.е. код будет добавляться а не заменяться).

            Если же размер типа не связан протоколом, а выбирается от балды - то лучше тайпдеф. Те же time_t, size_t и прочие они ведь неспроста тайпдефы.
            Ответить
            • P.S. В 2038 году страшная кара постигнет тех, кто писал int вместо time_t.

              (Я не о протоколах и форматах, с которыми совсем другая история, а о переменных).
              Ответить
              • > В 2038 году страшная кара постигнет тех, кто писал int вместо time_t.
                Доктор Стертор их заминусует.
                Ответить
              • "Если же размер типа не связан протоколом, а выбирается от балды - то лучше тайпдеф. Те же time_t, size_t и прочие они ведь неспроста тайпдефы."

                Нет. Самое лучшее - это нативный тип.

                Тайпдефы - только в случае если нужна совместимость с некрософтовским компилятором, потому что у них 64бит типы через жопу.

                "P.S. В 2038 году страшная кара постигнет тех, кто писал int вместо time_t."

                Это мелочи. На HP-UX time_t 64бит уже ХЕЗ как давно. Но. Редкая штатная функция времени не переваривает значения времени больше INT_MAX.
                Ответить
              • А также тех, кто использует проприетарный софт, существующих только в 32 битной версии. Столман предупреждал!
                Ну ладно PC, там 64 бита стремительно вытесняют 32, а вот что делать со встраиваемыми железками типа андроидов или домашних роутеров? Там 64 бита только-только начали появляться.
                Ответить
                • Столлман похож на того стереотипного мужика с плакатом - покайтесь, аппокалипсис близко!

                  Опять проблема 2000x64?
                  Ответить
                • > Там 64 бита только-только начали появляться.
                  Дык не надо 64-битную платформу. Надо всего лишь 64-битный time_t.
                  Ответить
                  • Ломать ABI и переходить на 64-битный time_t - это ж почти то же самое, что переходить на новую платформу.
                    Ответить
                    • ABI сломается, да. И старые бинарники не взлетят. Но API и совместимость на уровне исходников выживут (если не брать в расчет злобных буратин, которые пихали time_t в int).

                      Перейти на настоящую 64-битку будет всяко сложнее.
                      Ответить
    • Есть платформы, где размер байта отличен от 8 бит. На них размер uint32_t будет больше/меньше 4 байт. Может автор как раз и смотрел так далеко. Хотя, нужно видеть контекст, где используется данная конструкция.
      Ответить
      • Тип uint32_t всегда гарантированно 32-битный, на то он и uint32_t.
        Ответить
        • И если на платформе 16 битные байты, то sizeof(uint32_t) вернет 2.

          Так что гость все правильно сказал. Другое дело, что такие платформы днем с огнем не найти. DSP какие-нибудь разве что...
          Ответить
          • Разве не стандартные байты не ушли в прошлое вместе с ЭВМ- шкафами?
            Ответить
            • Разве IE6 не похоронили?
              Ответить
              • Да он раньше хряхи ушел в небытите - я им вообще почти не пользовался в времена ХР - сразу Оперу ставил.
                Ответить
                • Оттуда пошла шутка про "лучший сайт для IE - firefox.com/opera.com".
                  Ответить
              • >>Разве IE6 не похоронили?
                Перед тем, как что-то "хоронить", нужно найти адекватную замену.

                Самолет упал на необитаемый остров, в живых остались только два капитан, второй пилот и стюардесса.
                Через неделю жизни на острове капитан сказал: - хватит разврата. - и застрелил стюардессу.
                Еще через месяц капитан опять сказал: -хватит этого разврата! и похоронил стюардессу.
                -Хватит этого разврата, сказали пилот и капитан через пару дней, и выкопали стюардессу.
                Ответить
                • gk.ceqnt? kfkrb/
                  Ответить
                • Да выкинуть к прочь этот браузер из комплекта поставки операционки, по большому счету - в чем смотреть интернеты дело юзера.
                  Ответить
                  • >>по большому счету - в чем смотреть интернеты дело юзера.
                    С проводника или с WMP.
                    Ответить
                  • > Да выкинуть к прочь этот браузер из комплекта поставки операционки,
                    Дык IE 6 закопали же, вместе с операционкой, в которой он был в комплекте.

                    Олсо антимонопольщики евросоюза в свое время вытрясли с M$ версию без IE и WMP - Windows N.
                    Ответить
          • Сейчас всё настолько завязано на восьмибитные байты, что это предположение неявно делается в 95% байтозавязанного кода и на настолько нестандартных платформах он работать не будет.
            Ответить
          • в моем километре 1024 метра.
            Ответить
            • Ты хотел сказать кибиметре?
              Ответить
              • Да, неудачно получилось, учитывая, что приставки вполне точно определены.

                Тогда вот. В моем ярде - 4 фута!
                Ответить
      • > Есть платформы, где размер байта отличен от 8 бит.

        Да нет больше таких платформ...

        И даже те которые все еще живы, в С симулируют 8ми битные байты. Потому что иначе почти 100% софта на них не скомпилишь.
        Ответить
        • Есть 9, 16, и 32 битные, и даже выпускаются и разрабатываются до сих пор. И char`ы там тоже, 9, 16 и 32 битные соответственно, что ж тут эмулировать. Если верить интернет, есть даже 24 битные. Все зависит от стандарта. В POSIX, вроде, в байте обязательно должно быть 8 бит, поэтому, скорей всего, на таких не получится построить систему полностью совместимую с POSIX.
          Ответить
        • Правда это все почти DSP конечно же.
          Ответить
          • если речь про DSP, то там надо внимательно вглядыватся.

            для DSP есть проприетарные языки которые из далека (и часто с близи тоже) выглядят как С, но на самом деле есть всего лишь подмножества с проприетарными расширениями и специальными семантиками. (та же фигня с FPGA/friends.)

            и про POSIX в этом случае говорить не стоит, потому что (хотя я и не исключаю этой возможности) на них как правило никто операционки не использует. там народ почти все ручками пишет, с проприетарными либами производителя DSP.
            Ответить
    • А зачем разыменовывать результат sizeof()?
      Ответить
      • Да и многоточие в таком контексте не скомпилится.
        Ответить
        • потому что точки с запятой нет в конце.
          Ответить
        • Насколько помню последний стандарт разрешил использовать некоторые символы юникода в идентификаторах. Может это символ «троеточие» или три символа «малая точка» (U+0FE52)?
          Ответить
          • Символ троеточия гораздо уже, что каждый может проверить и лично убедиться.
            Ответить
      • Это умножение.
        Ответить
    • *sizeof(uint32_t) гораздо понятнее, чем *4.
      Ответить
    • Ну а что?
      #define NULL rand()
      Ответить
      • Это в C++. В С нужно ((int*)rand())
        Иначе заметят
        Ответить

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