Комментарии 28
sizeof(char)==1 Не значит что он занимает ровно один октет, может два и даже 3 на некоторых реально существующих архитектурах (для которых я писал код).
The definition of "byte" is defined in clause 3.4 of ISO/IEC 9899:1990
Basically, a byte is the size of a character. If a character is 16 bits then a byte is 16 bits.
Также автор этой статьи не до конца понимает зачем нужны стандартные типы:
- типы (u)intXX_t гарантируют представление знаковых данных в дополнительном коде и размер контейнера
- типы (u)int_leastXX_t, а не нестандартные at_leastXX_t гарантируют размер контейнера не менее заказанного
- (u)int_fastXX_t гарантируют оптимальное с точки зрения целочисленной арифметики представление данных и размер мантиссы не менее заказанного
Если в каком-то компиляторе они не определены, то это повод сменить компилятор, а при невозможности — исследовать компилируемый код для возможных типов данных и самому определить стандартные типы данных.
В любом случае использование стандартных типов данных (я имею в виду стандарты ISO C) имеет профит при повторном использовании кода по сравнению с использованием всяких непонятных и мутных типов BYTE, PWORD, at_leastXX, s16 и.т.п.
Кроме того грамотный разработчик включает код по контролю размеров и endian типов данных используемых в ABI в процедуры elementarу testing.
Насчет размерв char — спасибо, посмотрю.
Самому определить — на основе чего и как Вы это собираетесь сделать для компилятора, которого не видите? в этом и был посыл создания стандартных машинонезависимых типов, жаль что он не доведен до логического завершения.
И сомневаюсь, что сообщение о невозможности компиляции на данном конкретном компиляторе добавит поппулярности Вашей библиотеке — это по поводу контроля типов, хотя лишним точно не будет.
Конечно иногда интересно почитать цитаты «Энтропия, эргодический источник, многомерное пространство сообщений, биты, многосмысленность, процесс Маркова — все эти слова звучат весьма внушительно, в каком бы порядке их ни расположили. Если же расположить их в правильном порядке, они обретают определенное теоретическое содержание. И настоящий специалист порой может с их помощью найти решение повседневных практических задач» но не когда они составляют 90%.
Сразу же затрону тему беззнаковых чисел. Почему то сложилась практика, что для определении регистров внешних устройств (и при описании структуры пакетов передачи данных) применяют именно беззнаковые типы. Мне не очень понятно такое решение, поскольку единственное различие между знаковым и беззнаковым типом состоит в реализации операций > и <
Насколько мне известно, причина сего в том, что стандарт языка С описывает некоторые операции со знаковыми числами как неопределенное поведение, например:
- знаковое переполнение
- сдвиг отрицательных чисел влево
- сдвиг с залезанием в знаковый бит
Все это прекрасно может происходить при работе с регистрами.
Сдвиг отрицательных чисел вправо при этом является платформозависимым поведением и, в большинстве случаев, будет арифметическим (т.е. будет повторяться знаковый разряд). Скорее всего, это не то, что нужно при работе с регистром.
При определении пакетов передачи данных, разумеется, логичнее использовать тот тип, который подразумевается в пакете.
typedef enum {False=0,True=1} Boolean;
Нет ну сколько ж можно-то, ну 2016 год на дворе, стандарту С99 уже 17 лет, ему скоро в университет поступать можно, а вы все еще изобретаете свой bool! Ну есть же stdbool.h, сколько ж можно-то?
И опять ничего это не дает, неявное приведение к int'у все равно будет! А уж сколько замечательных столкновений с чужими определениями False, True и Boolean можно получить, просто сказка.
По поводу Boolean — я увидел в коде определение через char и показал более правильный вариант.
И Вы можете не согласиться, но мой вариант ругается в моем компиляторе (MinGW) при попытке присвоения логическому целого, а стандартный -нет, значит мой безопаснее.
К сожалению, в операторе сравнении оба варианта допускают целое, я знаю, как добиться правильного поведения в С++, а вот в С — нет.
Так что в этой части, позвольте остаться при своем мнении и изобретать велосипед.
Теперь немного о файлах. Не знаю, как Вам, но мне до сих пор (хотя прошел уже не один десяток лет) непривычно не найти в корневой директории проекта текстового файла с описанием структуры модулей и мест, где расположенные реализующие их файлы. Я понимаю, что скорее всего заголовочные файлы будут лежать в директории, название которой начинается с INC, а исходники в директории SRC, хотя тут уже есть варианты, вроде SOURCE, но в годы моей юности наличие такого файла считалось обязательным, не вижу оснований от подобной практики отказываться и текстовый файл, информирующий меня о авторе данного программного пакета и вида лицензии, под которой он был разработан, считаю совершенно недостаточным.
Вероятно, это дело вкуса, но лично мне не нравится, когда исходники и заголовочные файлы лежат в разных директориях. Почему?
- Это увеличивает дерево папок проекта, потому что папка каждого модуля (у вас же есть отдельные папки для модулей?) появляются в двух местах.
- Это заставляет вас либо писать путь в инклуде с какими-нибудь извращениями, вроде #include "../INC/header.h", либо прописывая путь до папки INC в настройках проекта или в makefile.
- Это не приносит никакой практической пользы.
Возможно, я каких-то бонусов просто не замечаю?
Сам я следую принципу «исходник и его заголовок лежат в одной папке, без разделения на SRC и INC», инклуд в исходнике при этом пишется просто #include «header.h». Дерево папок получается компактным, в настройках проекта ничего прописывать не нужно, инклуд получается короче.
Рискую быть непопулярным, но разве для вашего графоманства не нашлось темы поострее? Чего-нибудь менее замызганное и более желтушное? Например, «Предварительные оптимизации: 34 способа сделать вашей программе быстро.», «Стандарты C++: мифы и реальность» или «Течка памяти: случка указателей». Ну или «186 относительно честных способов отъёма прав администратора», на худой конец.
Почему то Джек Гансли не стесняется рассказывать на своих семинарах очевидные вещи, Барр в своем недельном семинаре 4 раза напоминает о перечислениях и их преимуществах а в моем опусе это приравнено к графомании. Я в начале ясно написал, в чем цель настоящего поста и ее достиг, на мой взгляд. Или Вы опять таки из тех, кто заявил в опросе, что мог бы прочитать такой курс лекций? Пока не вижу ни одного Вашего поста, который подтвердил бы Ваши притязания.
Ваш уровень как автора показал Ваш комментарий — Вы, наверное, пытались пошутить — не стоит, у Вас не получается. По крайней мере мне такие шуточки (то, что называется «сортирный юмор») перестали нравиться класса после 6-го, у Вас, похоже, этот период под-затянулся.
Интересно, если посмотреть на Ваш рейтинг и на мой, то Хабр в целом на моей стороне, что радует.
Ну и в заключение — хотелось бы посмотреть на Ваш код, несомненно он представляет собой образец стиля, судя по Вашим глубочайшим знаниям, или вы из теоретиков, которые стесняются показать свой код но всегда знают, как его надо делать?
Почему выступления перед студенческой публикой позволяют раз за разом поднимать подобную проблему? Потому как семинар и публикация на хабре, на котором каждый второй хвалит перечисления, — немного разные вещи. Потому как на семинаре не выходят 3-4 выступающих подряд хвалить одну и туже вещь, для которой хватило бы двух строчек. Собственно, это и есть основная моя претензия: всё вами изложенное могло поместиться в 33 строчки и не потеряло бы ни грамма смысловой нагрузки.
Я нахожусь в удобном положении читателя. Мне, как читателю, не обязательно указывать решения — достаточно поставить проблему. *Избитый пример про повара и блюдо*
Я поставил проблему: вы затянуто перечисляете либо очевидные молодому программисту вещи (тут я беру выпускников ВУЗов '12 года и позднее), либо рассуждаете о вкусовщине. При этом не раскрываете толком ничего. Вам, например, нужно иметь текстовик иметь с описанием имеющихся модулей, а мне вынь да положь doxygen'а кусок. Оба подхода имеют право на существование, но мой, как более современный, просто красивее. И ни один из них не спасает от ленивца, не заполняющего документацию, или заполняющего её не так, как вам нравится.
Одна проблема в ваших, да и не только ваших, публикациях очень ясно прослеживается — вы не даёте публикации настояться, дойти, исправить ошибки и убрать лишние куски текста. Я понимаю, иногда это сложно сделать, и нужно дать кому-либо оценить твой текст не предвзято. Я-то в чём виноват, когда издеваюсь над вашими прорехами? Не делайте их — и всё!
Ну и в заключении, о переходе на личности. Вы зашли на очень скользкую дорожку — оценку профессионализма по личностным характеристикам или оценке окружения. Если вы познакомитесь с достаточным числом программистов, ваша статистика вас разочарует.
Мой рейтинг не означает ничего, для его потери достаточно просто зайти в ветку с политикой или написать фанатам javascript, что он медленный или даже «а производительность этой фичи замеряли?». Мои публикации и их отсутствие так же не означают ничего, т.к. то, что я не нахожу в своей повседневной деятельности того, о чём имеет смысл написать не означает, что я ничего не понимаю. Рутина, знаете ли, не самая интересная вещь для публикации, но достаточно полезная для мозга в смысле поиска способов избавления себя от неё.
А вот о вас ваш призыв мериться рейтингами говорит достаточно много. Грубый наезд «да кто ты такой?!». Держу пари, если бы я стоял рядом, получил бы уже в глаз. Но проверять это, я, конечно же, не стану.
Я не очень понял про студенческую публику — перечисленные мной авторы курсов ориентированы скорее на профессионалов и курсы повышения квалификации.
Зайдите на любой профильный сайт (да что далеко ходить, посмотрите на Хабре примеры программ для микроконтроллеров, которыми делятся авторы) и для Вас станет ясно, что «очевидные молодому программисту вещи (тут я беру выпускников ВУЗов '12 года и позднее)», которые я «затянуто перечисляю» совершенно не очевидны и полностью игнорируются. Может быть, в том числе и потому, что выпускникам не объяснили их необходимость, что я пытаюсь делать по мере своих невеликих сил.
Если даже в моем, по Вашему мнению, затянутом опусе «При этом не раскрываете толком ничего.», было бы интересно наблюдать раскрытие темы в Ваших произведениях, либо в тех, которые Вы могли бы рекомендовать начинающему графоману для ознакомления с образцами.
И есть существенная разница между ленивцем, не заполняющем документацию, и заполняющим ее не так, как мне нравится — со вторым я готов смириться, но первый должен найти другую работу.
А про переход на личности — не я первый начал. Подразумевалось, что человек, обличающий в другом графоманские наклонности, должен быть готовым предъявить свои достижения, иначе его высказывания можно охарактеризовать известной цитатой «Критика Дон Жуана импотентами, при всей ее объективной справедливости, оставляет неприятный осадок».
Крайне огорчительно, что Вы в своей повседневной деятельности не находите ничего, о чем был бы смысл написать. Вы настолько не любите свою работу? Я в своей нахожу много интересного, вот и делюсь своими находками. Мои опусы читают, их заносят в избранное, значит, они не бесполезны.
Насчет получить в глаз — это Вы погорячились, это не в моем стиле, я думал, что это очевидно, но, видимо, ошибался.
PS. Рад, что образчики юмора упомянутого типа из вашего комментария исчезли.
Опять же, иной формат изложения.
Извольте, далеко не вся публика хабра имеет вышку, а из тех, кто имеет, далеко не всегда имеют профильную вышку. Ну да ладно, убедили.
Опять же, «чукча не писатель». Я не обязан показывать вам пример. Мне достаточно поставить проблему. Но если вы настаиваете, пункты «имена переменных» и «выражайтесь ясно» можно объединить в «пишите понятный код»:
«Какой код проще всего понять? Хорошо документированный или хорошо написанный? Сравните
int foo(int a, int b) // a power b
{
int c = 1;
while(b--) c *= a;
return c;
}
или
int power (int base, uint8_t exponent)
{
int product = 1;
for (uint8_t currentExponent = 1; currentExponent <= exponent; ++currentExponent ) {
product *= base;
}
return product;
}
Думаю, пояснения излишни. Пишите красивый и понятной код, ведь делать это просто, а читать — приятно. Конечно, далеко не всегда можно написать полностью самодокументируемый код, но оно и не нужно. Сегодня IDE и компиляторы всё равно делают за вас большую часть работы, так что не пишите для них. Пишите для людей: используйте понятные имена всех переменных и функций, помогайте компилятору и пользователям с помощью ключевых слов. Если знаете точный тип входных параметров, указывайте его явно. Используйте правильные формы имён: переменная — существительное, функция — глагол, флаги — вопросительное предложение и тп. И не заменяйте без особой надобности понятные записи алгоритмов на хитро оптимизированные. Не экономьте на спичках.»
Заметьте, по смыслу я практически полностью пересказал ваш текст. По объёму же получилось раза в 4 меньше, что гораздо проще читается. Неплохо?
Да-да, конечно, «обсуждение дам с девственниками». Слыхали уже. А теперь ответьте, вы сами читали свою статью? Как читатель, а не автор? Нет? Ну, тогда что мне с вами обсуждать? Получается, что ВЫ, мой уважаемый автор, тот самый «импотент», чья критика моих комментариев «при всей ее объективной справедливости, оставляет неприятный осадок». Вы предвзяты в своих суждениях, так как для вас любая критика — не просто чьё-либо мнение, а угроза вашему детищу. Я не могу осуждать вас за это. Хотя нет, постойте, могу.
PS. Рано радуетесь, он никуда не делся. Просто, кроме всего прочего, я наивно добрый человек, который действительно хочет помочь людям. А это требует несколько иного слога.
PPS Хватит мериться письками, у кого сколько рейтинга или публикаций. О чём предлагаете мне написать: «Парсинг хранимых процедур postgres для генерации исходников C++»? «Деобфускация инкриментных билдов java-приложений на примере клиента MMORPG»? Если для второго дострою тулзу, позволяющую транслировать имена между версиями, быть может, напишу. А так…
PPPS. Естественно, при отрицательном рейтинге тег CODE у меня не работает, так что кушайте так.
«Ну и зачем вы тогда вообще об этом вспомнили?» — так, между прочим, об этой стороне вспомнили именно Вы, похвалив меня за не приведение подобной, на мой взгляд, плохой рекомендации 1==хх. А потом именно Вы выражаете недоумение, зачем я вообще об этом вспомнил — прикольно.
«Заметьте, по смыслу я практически полностью пересказал ваш текст. По объёму же получилось раза в 4 меньше, что гораздо проще читается. Неплохо» — напоминает книжки «Вся русская классика 18-20 веков в 20 страницах», Вы не находите? Я ориентируюсь на другие эталоны — открываю Майерса и «правило 2: Предпочитайте const enum и inline использованию #define» занимает места больше, чем весь мой скромный опус. Мне кажется, что люди класса Майерса и Гансли знают о том, как надо рассказывать об особенностях встроенного программирования побольше, чем я (насчет Вас не уверен, судя по Вашему апломбу), поэтому с моей стороны вполне логично на них ориентироваться.
А насчет возможных тем — еще раз, жаль, что Вы так не любите свою работу. Я почему то вокруг себя вижу много замечательных тем для рассмотрения, в первую очередь для себя, а потом уже и для окружающих. Посмотрите повнимательнее вокруг себя, уверяю Вас, найдете о чем рассказать, и будет у Вас рейтинг положительный и сможете код писать, хотя я вполне смог скушать так.
Опять же, формат статьи отличается от формата книги как аудиторией, так и формой ознакомления с материалом. Если бы вы публиковали книгу, пускай и по главам, к вам были бы применимы совершенно другие критерии оценки. Но вы не Майерс, и публикуете не книгу, а статью, тем более, по вопросам типизации и оформления кода. Не научную работу, на которую похоже ваше оформление, а публицистическую (как минимум, научно-популярную, формат сайта такой). А это означает, в частности, короткое введение, больший объём примеров и меньший — логических обоснований. Вам не нужно что-либо доказывать, вам нужно коротко постулировать и аргументировать.
Прекратите выворачивать мои слова. Я написал, что мне не интересно писать о чём-либо ординарном, а не о том, что мне не интересна моя работа. Как только я открою для себя что-то действительно новое, вы обязательно увидите об этом пост. Но распыляться по мелочам ради циферок… Нет уж, спасибо.
Ну и конечно, не всякий способен аргументировать не доказывая, тогда зачем аргументировать, достаточно коротко постулировать.
Наверное, из за такого подхода перечисления все еще применяются крайне недостаточно.
И не ради циферок, просто 53 человека, которые мой пост занесли в избранное, наверное, навсегда запомнят преимущества перечислений, для чего и былданный пост написан.
Вот смотрите, я перегружаю в своём классе operator bool() const и запись if (myClass) становится осмысленной. Дальше я переопределяю operator bool() const класса shared_ptr, избавляясь от него, и лишаюсь ошибки случайной проверки указателя вместо класса. Далее, оборачиваю разные кейсы условий в отдельные методы, и избавляюсь от символов сравнения как таковых, а модификаторы const практически полностью защищают меня от случайного приравнивания. В итоге, я получаю куда более простую запись, создающую куда меньше ошибок. Далее, втыкаю в каждую дырку по constexpr, и получаю во многом эквивалентный вашему код, а где-то даже более оптимальный. С этой точки зрения ваш вариант с перечислениями недостаточно хорош. Единственная проблема — трудозатраты, так как идеальный код мы пишем для себя, а на работе нужно решать текущие проблемы, даже если тебе не нравится решение.
Ну, поздравляю их с этим. Хотя немного грустно, что они узнают об этих фичах не из обзорных статей по нововведениям в стандарт, а из достаточно поверхностных статей, в которых, например, ни слова о enum class, который в вашем примере куда более подходит под возвращаемый тип ошибки, так как не позволяет неявно перекастовывать себя в целочисленные поля или безнаказанно кастовать целое и Bool значения между собой (вызывая UB, если что). Плюс позволяет определять операторы и функции над перечислениями, которые действительно работают так, как нужно. Но об этом они не узнают, а жаль…
Может быть, Вы не заметили (хотя я честно написал, что знаю как сделать все правильно в С++, а в С не знаю), но в моем посте речь шла о чистом С. В плюсах существует множество полезных фич, это абсолютно верно, но они все не сработают в обычном С, даже в С99. Так что Ваш пафос абсолютно не по адресу. Можно было бы еще вспомнить жесткую типизацию в Аде, пользы принесло ровно столько же.
Прошу прощения, эта часть действительно от меня ускользнула, как ускользают и причины использования чистого C против «C с классами». Но в микроконтроллеры я не особо вхож, видимо, есть на то причины. А вот «C» можно было бы указать в тегах.
Насчет С Вы правы, надо было четко это указать, иначе становилось непонятно, зачем городить огород, а не применить сразу enum class, Вы верно его упомянули. Ну так исторически сложилось, что С пока однозначно лидирует и это приходится учитывать. Сразу поправлюсь — лидирует в программировании МК, о котором я исключительно и пишу, что, видимо, и послужило причиной определенного недопонимания между нами.
Что ж, похоже, мы достаточно друг с другом поспорили, пора и честь знать. Предлагаю вам в качестве пробы последовать моему совету и включать поменьше теории и умозрительных экспериментов в ваши статьи (или выносить её в спойлеры, оставляя в основной статье короткую выжимку). Попробуйте уложиться в 3-4 минуты чтения, отводя на введение не более 100 слов. Приводите максимально подробные примеры кода, но не более 15 строк за раз. Посмотрите на реакцию читателей, как они отреагируют на такой формат. А там уж посмотрим, может ли свежее поколение блеснуть знаниями перед бывалыми кодерами, или это очередное позерство выскочки-шестиклассника с его смехуючками.
используйте <stdbool.h> и <stdint.h>, тогда ваши программы не будут знать проблем с переносимостью)
А насчет <stdint.h> — несомненно, следует его использовать, речь шла всего лишь о ее недостатке в том, что некоторые типы не являются кобязательными к реализации и как этот недостаток нивелировать.
К вопросу о стиле