Массив общей длины массива для 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
?
- Почему это должно быть предпочтительным?
- Различаются ли они на С++?
Ответы
Ответ 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) Нет
Обратите внимание, что этот макрос не работает, если вызывается внутри функции, где массив передается в качестве параметра в функцию. Это связано с тем, что объект массива передавал "распады" в указатель, а не в глубокую копию.