Перейти к содержимому

Как создать массив нулей c

  • автор:

Arduino.ru

как заполнить сразу массив нулями при инициализации?

  • Войдите на сайт для отправки комментариев

19 ответов [Последнее сообщение]
Сб, 30/06/2018 — 21:31
Зарегистрирован: 10.04.2017

int arr [100] = <>; так ведь не работает?

  • Войдите на сайт для отправки комментариев

Сб, 30/06/2018 — 21:33
Зарегистрирован: 26.05.2017
SadiQ228 пишет:

int arr [100] = <>; так ведь не работает?

а зачем это вообще нужно?

По стандарту языка Си числовые типы инициализируются нулями автоматически.

  • Войдите на сайт для отправки комментариев

Сб, 30/06/2018 — 21:45
Зарегистрирован: 10.04.2017

и такие тоже? uint8_t

  • Войдите на сайт для отправки комментариев

Сб, 30/06/2018 — 22:02
Зарегистрирован: 10.04.2017

чтоб не плодить темы спрошу сразу.

а как присваивать несколько значений массивву? делаю так но не работает

как сделать похитрее?

  • Войдите на сайт для отправки комментариев

Сб, 30/06/2018 — 22:05
Зарегистрирован: 09.06.2016

  • Войдите на сайт для отправки комментариев

Сб, 30/06/2018 — 22:10
Зарегистрирован: 10.04.2017

это каждый раз будет создаваться массив, а хотелось бы использовать один и тот же

  • Войдите на сайт для отправки комментариев

Сб, 30/06/2018 — 22:14
Зарегистрирован: 09.06.2016

  • Войдите на сайт для отправки комментариев

Сб, 30/06/2018 — 22:39
Зарегистрирован: 09.06.2016
SadiQ228 пишет:

чтоб не плодить темы спрошу сразу.

а как присваивать несколько значений массивву? делаю так но не работает

как сделать похитрее?

присваивать значения массиву можно только при создании.

придется tmp[0]=0x00; tmp[1]=0xA4; tmp[2]=0x04; tmp[3]=0x00;

  • Войдите на сайт для отправки комментариев

Вс, 01/07/2018 — 10:17
Зарегистрирован: 25.02.2016
SadiQ228 пишет:

как сделать похитрее?

написать функцию присваивания, если Вам лень каждый раз индексы писать.

  • Войдите на сайт для отправки комментариев

Вс, 01/07/2018 — 11:38

trembo аватар

Зарегистрирован: 08.04.2011
reticular пишет:
SadiQ228 пишет:
присваивать значения массиву можно только при создании.

придется tmp[0]=0x00; tmp[1]=0xA4; tmp[2]=0x04; tmp[3]=0x00;

Никогда бы не догадался что оператор присваивания умеет работать только один раз. 🙂

  • Войдите на сайт для отправки комментариев

Вс, 01/07/2018 — 11:50
Зарегистрирован: 05.08.2014
SadiQ228 пишет:

это каждый раз будет создаваться массив, а хотелось бы использовать один и тот же

Судя по примеру достаточно менять tmp[0]. А так, в общем случае, поможет memcpy.

  • Войдите на сайт для отправки комментариев

Вс, 01/07/2018 — 17:18
Зарегистрирован: 24.09.2015

Да вот тоже интересно как заполнить массив данными .. Интересно, в плане допиливания тестовой проги под ATmega2560: надо объявить массив в PROGMEM для заливки скетча до упора флеш, которой там 256килов. Сам тест умещается в пару килобайт, а надо убедится что шьются все 256кб (уже имел опыт битого флеш) .. как-то руками приписывать лениво. 🙂

  • Войдите на сайт для отправки комментариев

Вс, 01/07/2018 — 21:30

andriano аватар

Зарегистрирован: 20.06.2015

Arhat109-2 , не совсем понял, что Вам нужно.

Если просто сформировать массив, который нужно залить во флешь, то проще всего написать маленькую программу (для ПК) которая сформирует исходник или его фрагмент в текстовом файле.

  • Войдите на сайт для отправки комментариев

Пнд, 02/07/2018 — 00:03
Зарегистрирован: 05.08.2014

Проще всего сгенерить длинную последовательност, как ПСЧ генерят. Пару строк кода в цикле залупят хоть гектар оригинальными данными. Проверить ею же.

  • Войдите на сайт для отправки комментариев

Пнд, 02/07/2018 — 08:19

andriano аватар

Зарегистрирован: 20.06.2015

Все так, только для проверки нужны не «оригинальные» данные.

  • Войдите на сайт для отправки комментариев

Пнд, 02/07/2018 — 10:07
Зарегистрирован: 24.09.2015

Да, всё верно: надо сгенерить заполнение флеша размером на 256 килобайт для заливки и последующего чтения, хотя бы силами avrdude во время заливки. Убедится что ВЕСЬ флеш пишется и читается как надо.

Ну я вот тоже пока не вижу иного способа как привлечь внешние системы для автогенерации «объемного» скетча — «написать программку для чего-либо», которая автосоздаст такой скетч.

Ещё пока мучаюсь с вариантом как проверить периферию в режиме «самотестирования» .. уж больно много ножек у этой меги. На каждую «светодиод» не повесишь.. и если UART порты ещё можно прогнать самотестированием, то вот замкнуть также I2C и SPI не очень понимаю получится ли то что хотелось..

P.S. Тест 512 килобайт памяти оказалось самой простой частью .. 🙂

  • Войдите на сайт для отправки комментариев

Пнд, 02/07/2018 — 15:01

wdrakula аватар

Зарегистрирован: 15.03.2016
Arhat109-2 пишет:

Ну я вот тоже пока не вижу иного способа как привлечь внешние системы для автогенерации «объемного» скетча — «написать программку для чего-либо», которая автосоздаст такой скетч.

Снова на арене? Мне не хватает ЧЮ, чтобы отличить — когда ты дурачишься, а когда и правда дурак.

В режиме бутлоадера тебе доступня вся память. Бери первый бутлоадер, в каталоге atmega, он проще, чем оптибут. Добавь туда проверку хоть всей памяти перед загрузкой или вместо загрузки, можешь ошибки в сериал вывести или и2с инициализировать. Там даже вариант для 128 учтен. С учетом размера кода придется корректировать фьюзы. В одном из бутлоадеров в ИДЕ закомментирована «интерактивная» часть. можешь посмотреть на ее примере.

После установки всех тулзов в Линухе, а ты вроде умеешь им пользоваться, бутлоадер просто собирается make ИМЯ_ЦЕЛИ. Только цель свою в мейкфайле создаешь.

Я писать тебе код более не стану — опять соврешь, что у тебя была «другая задача».

более того, ты вроде уже освоился в среде Ардуино? Сможешь добавить в меню своей платы хитрый пункт для самотестирования, при это заливаться будет программа самотестирования(о которой я написал выше) в режиме бутлоадера.

Опять же, после неоднократных проявлений говнистости характера — показывать — «как такое сделать» — не стану. А то опять будет «не та задача».

  • Войдите на сайт для отправки комментариев

Как создать массив нулей c

Как заполнить массив нулями раньше делал так
int32[] ar = new Int32[10];
в си делал так memset(ar,0,10);
Как в C# сделать?

Сообщ. #2 , 31.05.12, 04:28

Рейтинг (т): 202

в .NET не нужно обнулять память т.к. после инициализации она не содержит мусора, как это происходит в нативных языках. Я к тому, что после инициализации массив будет содержать значения, которые по-умолчанию принимает тип массива. В данном случае массив уже будет заполнен нулями.

Не очень понятен контекст использования. В какой ситуации это нужно? Если Вы работали с массивом, а потом Вам его просто нужно «обнулить», то воспользуйтесь методом Clear:

Массивы

П усть нам необходимо работать с большим количеством однотипных данных. Например, у нас есть тысяча измерений координаты маятника с каким-то шагом по времени. Создавать 1000 переменных для хранения всех значений очень. обременительно. Вместо этого множество однотипных данных можно объединить под одним именем и обращаться к каждому конкретному элементу по его порядковому номеру.
Массив в си определяется следующим образом
[];
Например,
int a[100];
Мы получим массив с именем a, который содержит сто элементов типа int. Как и в случае с переменными, массив содержит мусор.
Для получения доступа до первого элемента, в квадратных скобках пишем его номер (индекс). Например

#include #include void main()

Первый элемент имеет порядковый номер 0. Важно понимать, почему. В дальнейшем будем представлять память компьютера в виде ленты. Имя массива — это указатель на адрес памяти, где располагаются элементы массива.

Массив хранит адрес первого элемента. Индекс i элемента - это сдвиг на i*sizeof(тип) байт от начала

Индекс массива указывает, на сколько байт необходимо сместиться относительно начала массива, чтобы получить доступ до нужно элемента. Например, если массив A имеет тип int, то A[10] означает, что мы сместились на 10*sizeof(int) байт относительно начала. Первый элемент находится в самом начале и у него смещение 0*sizeof(int) .
В си массив не хранит своего размера и не проверяет индекс массива на корректность. Это значит, что можно выйти за пределы массива и обратиться к памяти, находящейся дальше последнего элемента массива (или ближе).

Начальная инициализация массива.

Н апишем простую программу. Создадим массив, после чего найдём его максимальный элемент.

#include #include void main() < int a[10] = ; unsigned i; int max; max = a[0]; for (i = 1; i max) < max = a[i]; >> printf("max element is %d", max); getch(); >

Разберём пример. Сначала мы создаём массив и инициализируем его при создании. После этого присваиваем максимальному найденному элементу значение первого элемента массива.

max = a[0];

После чего проходим по массиву. Так как мы уже просмотрели первый элемент (у него индекс 1), то нет смысла снова его просматривать.
Тот же пример, только теперь пользователь вводит значения

#include #include void main() < int a[10]; unsigned i; int max; printf("Enter 10 numbers\n"); for (i = 0; imax = a[0]; for (i = 1; i max) < max = a[i]; >> printf("max element is %d", max); getch(); >

В том случае, если при инициализации указано меньше значений, чем размер массива, остальные элементы заполняются нулями.

#include #include void main() < int a[10] = ; unsigned i; for (i = 0; i getch(); >

Если необходимо заполнить весь массив нулями, тогда пишем

int a[10] = ;

Можно не задавать размер массива явно, например

int a[] = ;

массив будет иметь размер 3

Размер массива

М ассив в си должен иметь константный размер. Это значит, что невозможно, например, запросить у пользователя размер, а потом задать этот размер массиву.

printf(«Enter length of array «); scanf(«%d», &length);

Создание динамических массивов будет рассмотрено дальше, при работе с указателями и памятью
В некоторых случаях можно узнать размер массива с помощью функции sizeof.

#include #include void main() < int A[57]; //sizeof возвращает размер всего массива в байтах //Для определения количества элементов необходимо //разделить размер массива на размер его элемента int size = sizeof(A) / sizeof(int); printf("Size of array equals to %d", size); getch(); >

Но это вряд ли будет полезным. При передаче массива в качестве аргумента функции будет передаваться указатель, поэтому размер массива будет невозможно узнать.
Статические массивы удобны, когда заранее известно число элементов. Они предоставляют быстрый, но небезопасный доступ до элементов.

Переполнение массива

П ускай у вас есть такой код

int A[10]; int i; for (i=0; i

  • 1. Используйте тип size_t для индексирования. Он обезопасит вас от отрицательных значений и его всегда хватит для массива любого размера.
  • 2. Помните, что массив начинается с нуля.
  • 3. Последний элемент массива имеет индекс (размер массива — 1)

Примеры

Т еперь несколько типичных примеров работы с массивами
1. Переворачиваем массив.

#include #include //Это макрос. SIZE в коде будет заменено на 10u #define SIZE 10u void main() < int A[SIZE] = ; unsigned i, j; //счётчики unsigned half; //середина массива unsigned tmp; //временная переменная для обмена значениями half = SIZE / 2; //Один счётчик идёт слева напрво, другой справа налево for (i = 0, j = SIZE - 1; i < half; i++, j--) < tmp = A[i]; A[i] = A[j]; A[j] = tmp; >for (i = 0; i < SIZE; i++) < printf("%d ", A[i]); >getch(); >

Здесь незнакомая для вас конструкция

#define SIZE 10u

макрос. Во всём коде препроцессор автоматически заменит все вхождения SIZE на 10u.
2. Удаление элемента, выбранного пользователем.

#include #include #define SIZE 10u void main() < int A[SIZE] = ; unsigned i; //счётчик int index; //индекс, введённый пользователем //Выводим массив for (i = 0; i < SIZE; i++) < printf("(%d)=%d ", i, A[i]); >//Просим пользователя ввести валидный индекс while (1) < printf("\nEnter index of element to delete "); scanf("%d", &index); if (index >0 && index < SIZE) < break; >> //Копируем следующий элемент массива на место удаляемого //и так до конца for (i = index; i < SIZE-1; i++) < A[i] = A[i+1]; >//Выводим результат for (i = 0; i < SIZE-1; i++) < printf("(%d)=%d ", i, A[i]); >getch(); >

Удаление элемента в данном случае, конечно, не происходит. Массив остаётся того же размера, что и раньше. Мы просто затираем удаляемый элемент следующим за ним и выводим SIZE-1 элементов.
3. Пользователь вводит значения в массив. После этого вывести все разные значения, которые он ввёл.
Пусть пользователь вводит конечное число элементов, допустим 10. Тогда заранее известно, что всего различных значений будет не более 10. Каждый раз, когда пользователь вводит число будем проходить по массиву и проверять, было ли такое число введено.

#include #include #define SIZE 10u void main() < int A[SIZE] = ; unsigned i, j; int counter = 1; //сколько разных чисел введено. Как минимум одно. int input; int wasntFound; //флаг, что введённое число не было найдено //Вводим первое число. Оно ещё не встречалось. printf("0. "); scanf("%d", &A[0]); for (i = 1; i < SIZE; i++) < printf("%d. ", i); scanf("%d", &input); wasntFound = 1; //Проверяем, встречалось ли такое число. Если да, //то выставляем флаг и выходим из цикла for (j = 0; j > //Если флаг был поднят, то заносим число в массив if (wasntFound) < A[counter] = input; counter++; >> for (i = 0; i < counter; i++) < printf("%d ", A[i]); >getch(); >

4. Пользователь вводит число — количество измерений (от 2 до 10). После этого вводит все измерения. Программа выдаёт среднее значение, дисперсию, погрешность.

#include #include #include #define SIZE 20u void main() < //Коэффициенты Стьюдента идут, начиная с двух измерений const float student[9] = ; float A[SIZE]; unsigned i; unsigned limit; float tmp; float sum = .0f; float mean; float disp; float absError; float relError; do < printf("Enter number of measurements "); scanf("%u", &limit); if (limit >1 && limit < 11) < break; >> while(1); for (i = 0; i < limit; i++) < printf("#%d: ", i); scanf("%f", &A[i]); sum += A[i]; >mean = sum / (float)limit; sum = .0f; for (i = 0; i < limit; i++) < tmp = A[i] - mean; sum += tmp * tmp; >disp = sum / (float)limit; absError = student[limit - 2] * sqrt(sum / (float)(limit - 1)); relError = absError / mean * 100; printf("Mean = %.6f\n", mean); printf("Dispertion = %.6f\n", disp); printf("Abs. Error = %.6f\n", absError); printf("Rel. Error = %.4f%", relError); getch(); >

5. Сортировка массива пузырьком

#include #include #define SIZE 10 #define false 0 #define true !false void main() < float a[] = ; float tmp; unsigned i, j; char flag; //Выводи массив for (i = 0; i < SIZE; i++) < printf("%.3f ", a[i]); >printf("\n"); //Пока массив не отсортирован do < flag = false; //Проходим по массиву. Если следующий элемент больше предыдущего, то //меняем их местами и по новой проверяем массив for (i = 1; i < SIZE; i++) < if (a[i] >a[i - 1]) < tmp = a[i]; a[i] = a[i - 1]; a[i - 1] = tmp; flag = true; >> > while(flag == true); //Выводим отсортированный массив for (i = 0; i < SIZE; i++) < printf("%.3f ", a[i]); >getch(); >

6. Перемешаем массив. Воспользуемся для этого алгоритмом Fisher-Yates:
Для i от N-1 до 1 выбираем случайное число j в пределах от 0 до i и меняем местами i-й и j-й элементы.

#include #include #include #include void main() < //Сегодня вместо макроса я решил использовать константу const int SIZE = 20; //Размер массива должен быть задан явно, как "константное выражение" int A[20] = < 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>; int i, rnd; int tmp; //Инициализируем генератор псевдослучайных чисел //В качестве начального числа берём системное время srand(time(NULL)); //Алгоритм Дюрштенфельда, модифицированный алгоритма Фишера-Ятса //Элементарный алгоритм, записать который легче, чем выучить название for (i = SIZE - 1; i > 0; i--) < rnd = rand() % i; //Случайное число в пределе от 0 до i tmp = A[i]; A[i] = A[rnd]; A[rnd] = tmp; >for (i = 0; i < SIZE; i++) < printf("%d ", A[i]); >getch(); >

ru-Cyrl 18- tutorial Sypachev S.S. 1989-04-14 sypachev_s_s@mail.ru Stepan Sypachev students

email

Всё ещё не понятно? – пиши вопросы на ящик

c++: инициализация небольших массивов и заполнение их нулями

а с чем это связано? интересно как это на уровне инструкций выглядит и там и там сам массив скорее всего сидит в стеке, во втором случае вызывается функция для заполнения его нулями, а вот что происходит в первом случае? правильно ли я понимаю, что при использовании оба случая идентичны относительно результата (т.е. все 10 ячеек всегда изначально заполнены 0)?

Отслеживать
задан 13 янв 2021 в 8:25
37.3k 4 4 золотых знака 28 28 серебряных знаков 72 72 бронзовых знака
А где здесь C++? Где std::array? Вижу только сишный массив.
13 янв 2021 в 8:28
Статья на хабре на эту тему.
13 янв 2021 в 8:32

Заявления в духе «эта конструкция работает быстрее, чем эта» следует подкреплять, добавив минимальный воспроизводимый пример.

13 янв 2021 в 8:43

@Никита Самоуков, а разве это не C++, вот если бы вы написали а где здесь STL? Где std::array? я бы понял, но метки stl у меня и не стоит 😉

13 янв 2021 в 8:47

Нормальный вопрос и для с++. Просто некоторые люди очень хотят, что бы сделать с++ не похожим на си и пойти дальше, использовать все-все фичи новейших стандартов.

13 янв 2021 в 8:50

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

интересно как это на уровне инструкций выглядит

это всегда легко узнать — https://gcc.godbolt.org/ покажет все.

Внутри интересно. я заметил, что студия на уровне /O0 /O1 не выбрасывает memset. Какой бы не был он быстрый внутри, это вызов функции. А вот первый способ превращается где то в такое

xor eax, eax mov ecx, 400 ; 00000190H rep stosb 

то есть, мы процессору говорим, в регистре ecx — количество, в eax — данные, рядом там есть ещё начало массива. И вперед.

А в одно время ребята с Интела посмотрели на это сказали — а давайте это будет распознаваться процессором как некая макрокоманда (и копирование памяти через префикс rep) и будет исполнятся прям внутри, а то и контроллером памяти. И это реально быстро. Детали можно найти в этом документе https://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-optimization-manual.pdf

gcc и clang для маленьких массивов просто берет и копирует регистр eax (куда предварительно записал ноль) в память без цикла — это тоже не медленно (память то в кеше).

А вот для больших массивов даже в первом случае clang вызывает memset.

Также интересно то, что gcc умеет распознавать memset как встроенную «магическую функцию» (то есть, он знает, что она делает) и заменять ее на «правильный» код.

Поэтому делаем выводы:

  • компиляторы хитры и знают много особенностей процессоров
  • если компилятор не понимает, что от него хотят — сделает общий код, что бы оно работало
  • минимальные изменения кода (размера массива) или версий компилятора могут приводить к большим перестроениям ассемблерных инструкций

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *