Почему люди используют переменную для указания номера пин-кода, когда он вряд ли изменится во время выполнения кода?
Много раз я видел, int
как используется для определения булавки,
int led = 13;
когда использование const int
const int led = 13;
#define LED 13
имеет гораздо больше смысла.
Это даже в учебниках на сайте Arduino, например, первом учебнике, который запускает большинство людей, Blink .
Я читал где-то, что const int
предпочтительнее, чем #define
. Почему это не поощряется с самого начала, а не позволяет людям развивать вредные привычки с самого начала? Я заметил это некоторое время назад, но в последнее время это начало меня раздражать, отсюда и вопрос.
Память / обработка / вычисления - это const int
, enum
или, в этом отношении #define
, лучше, чем обычное int
, то есть занимает меньше памяти, хранится в другой памяти (Flash, EEPROM, SRAM), быстрее выполняется, быстрее компилируется?
Это может показаться дубликатом. Лучше использовать #define или const int для констант? , но я обращаюсь к вопросу о том, почему люди используют переменные и как улучшается производительность, когда они этого не делают, а не то, какой тип константы лучше.
источник
Ответы:
Это правильный метод. Или даже:
Сколько у тебя булавок?
Некоторые учебные пособия не прошли такой контроль качества, как могли бы.
Производительность будет лучше при
const byte
сравнении,int
хотя компилятор может быть достаточно умен, чтобы понять, что вы делаете.Что вы можете сделать, так это мягко побудить людей использовать более эффективные методы, используя их в своем собственном коде.
Ответы на комментарии
Комментатор предположил, что
byte
это не стандартный C. Это правильно, однако это сайт Arduino StackExchange, и я считаю, что использование стандартных типов, предоставляемых Arduino IDE, приемлемо.В Arduino.h есть эта строка:
Обратите внимание, что это не совсем то же самое, что
unsigned char
. Смотрите uint8_t против неподписанного символа и когда uint8_t ≠ без знака? ,Другой комментатор предположил, что использование байта не обязательно улучшит производительность, потому что числа
int
будут меньше, чем будут повышатьсяint
(см. Правила продвижения по целочисленным значениям, если вы хотите узнать больше об этом).Однако в контексте идентификатора const компилятор в любом случае сгенерирует эффективный код. Например, разборка «мерцание» дает это в первоначальном виде:
На самом деле он генерирует тот же код, будь то
13
:#define
const int
const byte
Компилятор знает, когда он может поместить число в один регистр, а когда нет. Однако хорошей практикой является использование кодировки, которая указывает на ваши намерения . Делая это
const
ясно, что число не изменится, и делая этоbyte
(илиuint8_t
) ясно, что вы ожидаете небольшое число.Смущающие сообщения об ошибках
Другой важной причиной, по которой следует избегать,
#define
являются сообщения об ошибках, которые вы получаете, если допустили ошибку. Рассмотрим этот «мигающий» набросок с ошибкой:На первый взгляд все выглядит хорошо, но генерирует эти сообщения об ошибках:
Вы смотрите на первую выделенную строку (строка 4) и даже не видите символ «=». Плюс линия выглядит нормально. Теперь совершенно очевидно, в чем здесь проблема (
= 13
заменяетсяLED
), но когда строка на 400 строк дальше в коде, не очевидно, что проблема в том, как определяется светодиод.Я видел, как люди падали на это много раз (в том числе и я).
источник
int
это излишне ... то есть, пока Arduino наконец не выпустит доску Tera ... :-)byte
типа . Вы имеете в видуunsigned char
.byte
Вместо этого производительность не обязательно будет лучшеint
, поскольку в большинстве случаев целочисленное значение с типами меньше, чемint
предлагаетсяint
.C doesn't have a byte type. You mean unsigned char.
- Мой ответ был в контексте Arduino, который имеет этоtypedef uint8_t byte;
. Так что для Arduino, использованиеbyte
в порядке.Performance won't necessarily be better with byte instead of int
- см. исправленный пост.Как справедливо заявляет Игнасио, это в основном потому, что они не знают лучше. И они не знают лучше, потому что люди, которые учили их (или ресурсы, которые они использовали при обучении), не знали лучше.
Большая часть кода Arduino и учебные пособия написаны людьми, которые никогда не имели никакого опыта в программировании и очень "самообучаются" из ресурсов людьми, которые сами очень самоучки без надлежащего обучения программированию.
Многие фрагменты учебного кода, которые я вижу повсюду (и особенно те, которые доступны только в видеороликах YouTube - ург), были бы ошибкой, если бы я отмечал их на экзамене.
Да, a
const
предпочтительнее неконстантного, а даже более#define
, потому что:const
(вроде a#define
, в отличие от неконстантного) не выделяет ОЗУconst
(как неконстантный, но в отличие от a#define
) дает значение явного типаВторой момент здесь представляет особый интерес. Если специально не указано иное со встроенным приведением типов (
(long)3
) или суффиксом типа (3L
) или наличием десятичной точки (3.0
),#define
a числа всегда будет целым числом, и вся математика, выполняемая с этим значением, будет выглядеть так, как если бы она была целое число. В большинстве случаев это не проблема, но вы можете столкнуться с интересными сценариями, когда вы попытаетесь#define
найти значение, которое больше, чем может хранить целое число, например, а#define COUNT 70000
затем выполнить математическую операцию с другимиint
значениями. Используя a,const
вы получаете сообщение компилятору «Это значение следует рассматривать как этот тип переменной», поэтому вместо этого вы должны использовать:const long count = 70000;
и все будет работать так, как ожидается.Он также имеет эффект приведения в действие, который проверяет тип при передаче значения по месту. Попробуйте передать
const long
функцию, которая ожидает,int
и она будет жаловаться на сужение диапазона переменных (или даже полностью не компилируется в зависимости от сценария). Сделайте это с помощью a,#define
и он будет просто молча продолжать давать вам неправильные результаты и заставит вас часами чесать голову.источник
const
переменной может потребоваться оперативная память, в зависимости от контекста, например, если она инициализируется с использованием возвращаемого значения из функции non-constexpr.const int foo = 13; bar(&foo);
же определенно потребует, чтобы компилятор выделил фактическую память дляfoo
.int
компиляторе, то оно обрабатывает значение как имеющее наименьший тип, в который оно будет помещаться (по модулю правил для подписанного и неподписанного). Если вы работаете в системе сint
16 битами,#define count 70000
результат будетcount
выглядеть как along
, как если бы он был определен какconst long count = 70000;
. Кроме того, если вы передадите любую из этих версийcount
ожидающей функцииint
, любой здравомыслящий компилятор будет обращаться с ними одинаково.#define COUNT 70000
не усекается в int, но компилятор обрабатывает его как тип, достаточно большой, чтобы содержать это число. Это правда, что когда вы используете, это может быть неочевидно, еслиCOUNT
это не int, но выconst long
все равно можете сказать то же самое .COUNT
в вашем примере заменяется перед компиляцией с выражением70000
, которое имеет тип , определенный по правилам литералов, так же , как2
и13L
или4.0
определяется правилами литералов. Тот факт, что вы используете#define
псевдонимы этих выражений, не имеет значения. Вы можете использовать#define
для псевдонимов произвольные куски кода C, если хотите.Как двухнедельный новичок в Arduino, я бы понял общую идею, что Arduino занят непрограммистами. Большинство эскизов, которые я исследовал, в том числе на сайте Arduino, демонстрируют полное отсутствие порядка, причем эскизы не работают, и в поле зрения есть только связный комментарий. Блок-схемы отсутствуют, а «Библиотеки» - это немодерируемый беспорядок.
источник
Мой ответ ... они делают это, потому что это работает. Мне трудно не задавать вопрос в своем ответе, например, «почему это должно быть« неправильно »?»
источник