Работает ли конструкция int array[100] = {0} на Arduino?

Я компилирую свой код в Arduino IDE. У меня есть массив, который я хочу инициализировать 0. Я знаю, что memset работает на Arduino, но я привык к этому из моей практики программирования на C++ для настольных компьютеров:

int array[100] = {0};

Я не смог найти никакой информации о том, работает ли эта конструкция на Arduino. Я думаю, что так и должно быть, поскольку он использует компилятор GCC. Несмотря на то, что он может быть изменен, я все же ожидаю, что он останется совместимым с C и C++. Тем не менее, можете ли вы подтвердить, что эта стандартная конструкция C/C++ работает на Arduino?

, 👍0

Обсуждение

Ты пробовал это? Каковы результаты?, @Majenko

@Majenko: Кажется: программа намного больше с = {0}, чем без него, поэтому компилятор определенно делает _что-то_. С другой стороны, в моем тесте массив состоял из 0 как с = {0}, так и без него. Проблема в том, что это ничего не доказывает. Это не гарантирует, что он будет работать на каком-то другом компиляторе с другими настройками. Тестирование будет окончательным только в том случае, если оно продемонстрирует, что этот код **не** работает., @Violet Giraffe

Это делает не компилятор (и = {0}, кстати, ничего не делает), а CRT (код инициализации). Может быть, это объяснит: https://en.wikipedia.org/wiki/.bss, @Majenko

@Majenko: а) если он ничего не делает, компилятор Arduino IDE не работает: http://stackoverflow.com/a/629063/634821 б) почему он ничего не делает, когда увеличивает размер кода на пару сотен байт?, @Violet Giraffe

= {0}, возможно, предотвратил оптимизацию неиспользуемой переменной из кода., @Majenko

@Majenko: он очень часто использовался, я печатал его в Serial в setup()., @Violet Giraffe

Возможно, он изменил способ инициализации до нуля — явно очистив этот блок памяти, а не просто полагаясь на уже очищенную BSS. Таким образом, это может изменить *поведение*, но не конечный результат - и в конечном итоге просто без необходимости увеличивает размер вашей программы., @Majenko

вы действительно можете попробовать и увидеть это, распечатав на последовательном мониторе :), @Manav

@Manav: Да, смотрите мой первый комментарий к Маженко. Это ничего не доказывает, если кажется, что он работает правильно. Только отрицательный результат будет окончательным., @Violet Giraffe

Вы должны начать с предположения, что Arduino использует стандартный C++ (однако исключения отключаются переключателем командной строки). Если что-то стандартное C++, то оно будет работать. Вам не нужно беспокоиться о том, чтобы доказать это., @Nick Gammon


3 ответа


Лучший ответ:

4

Я привык к этому из моей практики программирования на C++ для настольных компьютеров:

int array[100] = {0};

Я не смог найти никакой информации о том, работает ли эта конструкция на Arduino.

Тип ={0} не имеет фактического действия. Это то же самое, что:

int array[100];

Неинициализированные статические/глобальные переменные и переменные, для которых явно задано значение 0, помещаются в раздел памяти .bss. .

Этот раздел инициализируется 0 кодом CRT (C Runtime) (код запуска для системы).

Компилятор отвечает за размещение этих переменных в .bss, но задача кода запуска (CRT) состоит в том, чтобы инициализировать его нулем.

Это стандартная операция языка C, и вряд ли она когда-либо изменится, так как может нарушить множество вещей.

Примечание: это НЕ относится к локальным переменным, расположенным в стеке. Эти должны быть инициализированы 0, если вы хотите, чтобы они начинались с 0.

,

Очень хорошо, спасибо за объяснение. У меня нет привычки полагаться на типы POD, инициализирующие C по умолчанию (потому что это обычно не так), и, следовательно, я предпочитаю делать это явно, но у меня также нет привычки часто использовать глобальные или статические данные. Не знал, что глобальные переменные гарантированно будут инициализированы по умолчанию (или инициализированы нулями? Я всегда путаю эти два термина). Суть = {0} заключается в том, что он также работает для локальных массивов., @Violet Giraffe


4

Кросс-компиляторы GNU для Arduino используют внешние интерфейсы C/C++ и соответствуют спецификациям языка. Вы можете ожидать полностью совместимый результат. «Язык Arduino» — неправильное название. Среда разработки Arduino будет пытаться помочь новым программистам, например, автоматически обнаруживая ссылки на библиотеки и вставляя необходимые #includes для вас, но полученный код будет C++ и представлен компилятору C++. IDE предоставляет функцию main(), которая вызывает setup() и loop()serialEventRun()). если вы его предоставите), тем самым напоминая программисту инициализировать все, что необходимо инициализировать, прежде чем ожидать, что все будет работать правильно. Однако вы можете написать правильный C++ и получить то, что ожидаете. Вам придется действовать «за спиной IDE», чтобы подавить автоматически предоставляемую функцию main(), но инструментальной цепочке все равно, как эта часть была выполнена, если есть один.

Я тестировал эту тривиальную программу:

массив целых чисел[100];

void setup() {
  // put your setup code here, to run once:
   for(uint8_t i = 0; i < sizeof(array); ++i)
      array[i] = i;
}

void loop() {
  // put your main code here, to run repeatedly:

}

как с Arduino IDE, так и со Sloeber — Eclipse с подключаемым модулем EclipseArduino, который регулярно предоставляет базовую карту памяти после компиляции, а также с выражением инициализации = {0} и без него. Я не обнаружил разницы в размере вывода в любой среде, с инициализацией или без нее. Во всех четырех случаях размер .bss составлял 209 байт, что на 200 байт больше, чем без глобального массива.

,

5

Эта конструкция работает в Arduino IDE. На самом деле, ={ 0 — одна из знаковых идиом языка C. Его можно использовать для инициализации нулями объекта любого типа в C. В C++ все немного сложнее. Это будет работать для массива int [100], но в общем случае вам может быть лучше использовать инициализатор = {} для достижения того же эффекта, где это применимо.

Непонятно, почему в принятом ответе утверждается, что эта конструкция «не имеет фактического эффекта». Это, конечно, неправильно. Точнее, этот инициализатор является избыточным ("не имеет никакого эффекта") для переменных со статической продолжительностью хранения, поскольку такие переменные в любом случае инициализируются по умолчанию (инициализируются нулем для int [100]), даже если вы не запрашиваете его явно. Но для объявления local переменная эффект = { 0 } неоспорим и очевиден: он инициализирует массив нулями (который не был бы инициализирован без этого ).

Обратите внимание, что несмотря на то, что 0 в = { 0 } инициализирует первый элемент массива, этот инициализатор в конечном итоге запускает нулевую инициализацию, если весь массив.

,