Существует интересный макрос, который используется для определения количества элементов в объявленном массиве. Его обычное определение выглядит так:
#define N_ELEMENTS(X) (sizeof(X)/sizeof(*(X)))
Данный макрос удобно применять для перебора всех элементов массива в циклах.
void foo(void)
{
uint8_t bar[] = {0, 1, 2, 3, 4};
uint8_t i;
/* передать каждый элемент массива bar[] */
for (i = 0; i < N_ELEMENTS(bar); ++i){
txc(bar[i]);
}
}
Это похоже на цикл foreach, который есть в языках PHP и C#. Макрос полезный, но в чем его преимущество перед стандартным подходом?
Обычно для определения размера массива используется именованная константа. Она же в дальнейшем применяется в качестве ограничителя в циклах. Примерно так:
#define BUF_SIZE (5)
void foo(void)
{
uint8_t bar[BUF_SIZE] = {0, 1, 2, 3, 4};
uint8_t i;
/* передать каждый байт массива bar[] */
for (i = 0; i < BUF_SIZE; ++i){
txc(bar[i]);
}
}
Если преднамеренно или случайно массив будет объявлен с другим количеством элементов, то цикл выполнится некорректно.
#define BUF_SIZE (5)
void foo(void)
{
uint8_t bar[BUF_SIZE + 1] = {0, 1, 2, 3, 4, 5};
uint8_t i;
/* передать каждый байт массива bar[] */
for (i = 0; i < BUF_SIZE; ++i){
txc(bar[i]);
}
}
Очевидно, что последний элемент массива в цикле for не будет передан.
Тот же код, но с применением макроса N_ELEMENTS дает корректный результат в обоих случаях – перебираются все элементы массива. Поэтому точки зрения надежности, такой код будет лучше.
#define BUF_SIZE (5)
void foo(void)
{
uint8_t bar[BUF_SIZE + 1] = {0, 1, 2, 3, 4, 5};
uint8_t i;
/* передать каждый байт массива bar[] */
for (i = 0; i < N_ELEMENTS (bar); ++i){
txc(bar[i]);
}
}
По материалам блога Найджела Джонса
.
Comments
Попробуйте передать свой массивчик bar в какую-то функцию - например, как это бывает - для сортировки или нахождения максимального значения....
Главное - всё скомпилится, никто никого не предупредит о подляне - но посмотрите как это будет работать))
А старый добрый #define - и здесь не подведёт...
RSS feed for comments to this post