Подтвердить что ты не робот

Массив общей длины массива для C?

Я видел несколько макросов для длины массива, плавающей вокруг:

Из этот вопрос:

  • #define length(array) (sizeof(array)/sizeof(*(array)))
  • #define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
  • #define SIZE(array, type) (sizeof(array) / (sizeof(type))

И Visual Studio _countof:

#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))

Что я хотел бы знать:

  • Какая разница между теми, кто использует array[0] и *array?
  • Почему это должно быть предпочтительным?
  • Различаются ли они на С++?
4b9b3361

Ответ 1

Здесь лучше C-версия (из проекта Google Chromium):

#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))

Он улучшает версию array[0] или *array, используя 0[array], что эквивалентно array[0] на простых массивах, но не скомпилируется, если array оказывается типом С++, который перегружает operator[]().

Разделение вызывает операцию "разделить на нуль" (которая должна быть уловлена ​​во время компиляции, поскольку она является выражением постоянной времени компиляции) для многих (но не для всех) ситуаций, когда указатель передается как параметр array.

См. Есть ли стандартная функция в C, которая вернет длину массива? для получения более подробной информации.

Там лучший вариант для кода на С++. Подробнее см. Время компиляции sizeof_array без использования макроса.

Ответ 2

  • Какая разница между теми, которые используют массив [0] и * array?
  • Почему это должно быть предпочтительным?
  • Различаются ли они на С++?

(1) Никакой разницы в C. Нет разницы для реального исходного массива в С++.

(2) Нет технических оснований для предпочтения одного или другого, но новички могут быть смущены разыменованием указателя.

(3) В С++ вы обычно не используете макрос, потому что он очень опасен. Если вы передадите указатель вместо фактического необработанного массива, код будет компилироваться, но даст неверный результат. Поэтому в С++ вы должны/должны вместо этого использовать шаблон функции, например & hellip;

#include <stddef.h>

typedef ptrdiff_t Size;

template< class Type, Size n >
Size countOf( Type (&)[n] ) { return n; }

Это только принимает фактический необработанный массив в качестве аргумента.

Это часть триады функций startOf, endOf и countOf, которую очень удобно определить, чтобы они могли применяться как к необработанным массивам, так и к стандартным библиотечным контейнерам. Насколько я знаю, эта триада была впервые идентифицирована Дитмаром Кюлем. В С++ 0x startOf и endOf, скорее всего, будут доступны как std::begin и std::end.

Приветствия и hth.,

Ответ 3

1) Ничего, значение массива является указателем на его первый элемент. Итак * array == array [0]
2) Личные предпочтения
3) Нет

Обратите внимание, что этот макрос не работает, если вызывается внутри функции, где массив передается в качестве параметра в функцию. Это связано с тем, что объект массива передавал "распады" в указатель, а не в глубокую копию.