Зачем использовать переменную int для булавки, когда const int, enum или #define имеет больше смысла
Почему люди используют переменную для указания номера штыря, когда штырь вряд ли изменится во время выполнения кода?
Много раз я вижу int
для определения вывода,
int led = 13;
, когда использование const int
const int led = 13;
#define LED 13
имеет гораздо больше смысла.
Это даже в учебниках на сайте Arduino, например, в первом учебнике, которое большинство людей запускает, прочитайте где-нибудь что const int
предпочтительнее #define
. Почему это не поощряется с самого начала, а не позволяет людям развивать вредные привычки с самого начала? Я заметил это некоторое время назад, но в последнее время это начало раздражать меня, следовательно, вопрос.
Память /обработка /вычисление wise - это const int
, enum
или, если это важно, #define
, лучше обычного int
, т.е. занимает меньше памяти, хранящейся в различной памяти (Flash , EEPROM, SRAM), быстрее выполнять, быстрее компилировать?
Это может быть дубликат Лучше ли использовать #define или const int для констант? , но я обращаюсь к вопросу о том, почему люди используют переменные и как производительность улучшается, когда они этого не делают, а не какой тип константа лучше.
4 ответа
const int led = 13;
Это правильный метод. Или даже:
const byte led = 13;
Сколько у вас контактов?
В некоторых учебниках не так много контроля качества, как они могли бы быть.
Производительность будет лучше использовать const byte
, сравните с int
, однако компилятор может быть достаточно умным, чтобы понять, что вы делаете.
Что вы можете сделать, это мягко поощрять людей использовать более эффективные методы, используя их в своем собственном коде.
Ответы на комментарии
-
Комментировщик предположил, что
byte
не является стандартным C. Это правильно, однако это сайт Arduino StackExchange, и я считаю, что использование стандартных типов, поставляемых с помощью Arduino IDE, приемлемо.В Arduino.h есть такая строка:
typedef uint8_t byte;
Обратите внимание, что это не совсем то же самое, что
unsigned char
. См. uint8_t vs unsigned char и Когда is uint8_t â ‰ unsigned char? . -
Другой комментатор предположил, что использование байта не обязательно улучшит производительность, потому что числа, меньшие, чем
int
, будут переведены наint
(см. Правила целых рекламных кампаний, если вы хотите больше на это).Однако в контексте идентификатора const компилятор будет генерировать эффективный код в любом случае. Например, демонтаж «мигает» дает это в оригинальной форме:
00000086 <loop & gt ;: 86: 8d e0 ldi r24, 0x0D; 13 88: 61 e0 ldi r22, 0x01; 1 8a: 1b d1 rcall. + 566; 0x2c2 <digitalWrite>
Фактически он генерирует один и тот же код:
13
:- Литерал
- Является
#define
- Является
const int
- Является
const byte
Компилятор знает, когда он может поместить число в один регистр и когда он не может. Тем не менее, хорошая практика использует кодировку, указывающую на намерение . Создание кода const
дает понять, что номер не изменится и сделает его byte
(или uint8_t
) дает понять, что вы ожидаете небольшое число.
Сбивание сообщений об ошибках
Еще одна важная причина избежать #define
- это сообщения об ошибках, которые вы получаете, если ошибаетесь. Рассмотрим этот «мигающий» эскиз, который имеет ошибку:
#define LED = 13;
void setup () {
pinMode (LED, OUTPUT); //<---- строка с ошибкой
}
void loop () {
digitalWrite (LED, HIGH); //<---- строка с ошибкой
Задержка (1000);
digitalWrite (LED, LOW); //<---- строка с ошибкой
Задержка (1000);
}
Поверхность выглядит нормально, но генерирует эти сообщения об ошибках:
Blink.ino: В функции â € ~void setup () â € ™:
Blink: 4: ошибка: ожидаемое первичное выражение перед â € ~ = â € ™ token
Blink: 4: ошибка: ожидаемое первичное выражение перед â € ~, â € ™ token
Blink: 4: ошибка: ожидается `; ' до â € œ ""
Blink.ino: В функции âvoid loop () â € ™:
Blink: 8: ошибка: ожидаемое первичное выражение перед â € ~ = â € ™ token
Blink: 8: ошибка: ожидаемое первичное выражение перед â € ~, â € ™ token
Blink: 8: error: expected `; ' до â € œ ""
Blink: 10: ошибка: ожидаемое первичное выражение перед â € ~ = â € ™ token
Blink: 10: ошибка: ожидаемое первичное выражение перед â € ~, токеном
Blink: 10: ошибка: ожидается `; ' до â € œ ""
Вы просматриваете первую выделенную строку (строка 4) и даже не видите символ "=". Кроме того, линия выглядит отлично. Теперь довольно очевидно, что проблема здесь (= 13
заменяется на LED
)), но когда строка содержит 400 строк дальше в коде, это не очевидно, проблема связана с тем, как определяется светодиод.
Я видел, как люди падали много раз (включая меня).
Как справедливо заявляет Игнасио, это в основном потому, что они не знают лучше. И они не знают лучше, потому что люди, которые их учили (или ресурсы, которые они использовали при обучении), не знали лучше.
Большая часть кода и учебных пособий Arduino написана людьми, которые никогда не занимались программированием и очень «самоучиваются» из ресурсов людьми, которые сами очень самоучительны, без надлежащей подготовки к программированию.
Многие из фрагментов кода учебника, который я вижу по всему месту (и особенно тех, которые доступны только в видеороликах YouTube --- urgh), были бы ошибкой, если бы я их маркировал на экзамене.
Да, a const
предпочтительнее неконстантного и даже над #define
, потому что:
- A
const
(например,#define
, в отличие от неконстантного) не выделяет никакой ОЗУ - A
const
(как не-const, но в отличие от#define
) дает значение a type
Второй момент представляет особый интерес. Если специально не указано иное с внедренным типом ((long) 3
) или суффиксом типа (3L
) или наличием десятичной точки (3.0
), #define
всегда будет целым числом, и вся математика, выполняемая над этим значением, будет выглядеть так, как если бы она была целым числом. В большинстве случаев это не проблема, но вы можете столкнуться с интересными сценариями при попытке #define
сохранить значение, которое больше, чем целое число, например #define COUNT 70000
, а затем выполнить математическую операцию с другими значениями int
. Используя const
, вы можете сообщить компилятору «Это значение должно рассматриваться как этот тип переменной» - поэтому вместо этого вы должны использовать: const long count = 70000;
и все будет работать так, как ожидалось.
Он также имеет эффект постукивания, который проверяет тип при передаче значения вокруг места. Попробуйте передать const long
функцию, ожидающую int
, и она будет жаловаться на сужение диапазона переменных (или даже полностью не скомпилировать в зависимости от сценария). Сделайте это с помощью #define
, и он просто молча продолжит давать вам неправильные результаты и оставит вас царапать вашу голову часами.
Мой ответ: они делают это, потому что это работает. Мне трудно задавать вопрос в моем ответе, например «почему это должно быть« неправильно »?»
Как двухнедельный новичок в Arduino, я бы взял общую идею о том, что Ардуино занимают не-программисты. Большинство эскизов, которые я рассмотрел, в том числе на сайте Arduino, показывают полное отсутствие порядка, с эскизами, которые не работают & едва заметный комментарий. Блок-схемы не существуют, а «Библиотеки» являются неуправляемыми беспорядками.