Как определить размер моего массива в C? - PullRequest
835 голосов
/ 01 сентября 2008

Как определить размер моего массива в C?

То есть количество элементов, которое может содержать массив?

Ответы [ 21 ]

1059 голосов
/ 01 сентября 2008

Резюме:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

Полный ответ:

Чтобы определить размер вашего массива в байтах, вы можете использовать sizeof Оператор:

int a[17];
size_t n = sizeof(a);

На моем компьютере длина строки составляет 4 байта, поэтому n равно 68.

Чтобы определить количество элементов в массиве, мы можем разделить общий размер массива по размеру элемента массива. Вы можете сделать это с типом, как это:

int a[17];
size_t n = sizeof(a) / sizeof(int);

и получите правильный ответ (68/4 = 17), но если тип a изменено, у вас будет неприятная ошибка, если вы забудете изменить sizeof(int).

Таким образом, предпочтительным делителем является sizeof(a[0]), размер Нулевой элемент массива.

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

Еще одним преимуществом является то, что теперь вы можете легко параметризовать имя массива в макросе и получим:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);
706 голосов
/ 27 апреля 2012

Правильный путь sizeof если вы имеете дело с массивами, не полученными в качестве параметров. Массив, отправленный в качестве параметра функции, рассматривается как указатель, поэтому sizeof будет возвращать размер указателя, а не массива.

Таким образом, внутри функций этот метод не работает. Вместо этого всегда передавайте дополнительный параметр size_t size, указывающий количество элементов в массиве.

Тест:

#include <stdio.h>
#include <stdlib.h>

void printSizeOf(int intArray[]);
void printLength(int intArray[]);

int main(int argc, char* argv[])
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6 };

    printf("sizeof of array: %d\n", (int) sizeof(array));
    printSizeOf(array);

    printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
    printLength(array);
}

void printSizeOf(int intArray[])
{
    printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}

void printLength(int intArray[])
{
    printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}

Вывод (в 64-битной ОС Linux):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2

Вывод (в 32-битной ОС Windows):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
119 голосов
/ 01 сентября 2008

Стоит отметить, что sizeof не помогает при работе со значением массива, которое распалось на указатель: даже если оно указывает на начало массива, для компилятора оно совпадает с указателем на один элемент этого массива. Указатель не «запоминает» что-либо еще о массиве, который использовался для его инициализации.

int a[10];
int* p = a;

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
44 голосов
/ 15 октября 2008

Размер «трюка» - лучший способ, который я знаю, с одним небольшим, но (для меня это крупная любимая мозоль) важным изменением в использовании скобок.

Как видно из записи в Википедии, C * sizeof не является функцией; это оператор . Таким образом, он не требует скобок вокруг своего аргумента, если аргумент не является именем типа. Это легко запомнить, поскольку аргумент выглядит как приведенное выражение, которое также использует круглые скобки.

Итак: если у вас есть следующее:

int myArray[10];

Количество элементов с кодом можно найти следующим образом:

size_t n = sizeof myArray / sizeof *myArray;

Это, для меня, читается намного проще, чем альтернатива с круглыми скобками. Я также предпочитаю использовать звездочку в правой части раздела, поскольку она более краткая, чем индексирование.

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

Всегда лучше использовать sizeof для реального объекта, когда он у вас есть, а не для типа, поскольку тогда вам не нужно беспокоиться о том, чтобы сделать ошибку и указать неверный тип.

Например, скажем, у вас есть функция, которая выводит некоторые данные в виде потока байтов, например, по сети. Давайте вызовем функцию send() и заставим ее принимать в качестве аргументов указатель на объект для отправки и количество байтов в объекте. Итак, прототип становится:

void send(const void *object, size_t size);

А затем вам нужно отправить целое число, чтобы вы кодировали его следующим образом:

int foo = 4711;
send(&foo, sizeof (int));

Теперь вы ввели тонкий способ выстрелить себе в ногу, указав тип foo в двух местах. Если одно меняется, а другое нет, код ломается. Таким образом, всегда делайте это так:

send(&foo, sizeof foo);

Теперь вы защищены. Конечно, вы дублируете имя переменной, но вероятность того, что компилятор может обнаружить ее, если вы ее измените, высока.

36 голосов
/ 08 декабря 2013
int size = (&arr)[1] - arr;

Проверьте эту ссылку для объяснения

25 голосов
/ 27 мая 2017

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

len = sizeof(arr)/sizeof(arr[0])

Код, первоначально найденный здесь: C программа для поиска количества элементов в массиве

20 голосов
/ 18 января 2014

Если вы знаете тип данных массива, вы можете использовать что-то вроде:

int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22};

int noofele = sizeof(arr)/sizeof(int);

Или, если вы не знаете тип данных массива, вы можете использовать что-то вроде:

noofele = sizeof(arr)/sizeof(arr[0]);

Примечание: эта вещь работает, только если массив не определен во время выполнения (например, malloc) и массив не передан в функцию В обоих случаях arr (имя массива) является указателем.

16 голосов
/ 28 февраля 2014

Макрос ARRAYELEMENTCOUNT(x), который каждый использует, оценивает неправильно . На самом деле это просто деликатный вопрос, потому что у вас не может быть выражений, которые приводят к типу «массив».

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0]))

ARRAYELEMENTCOUNT(p + 1);

На самом деле оценивается как:

(sizeof (p + 1) / sizeof (p + 1[0]));

Принимая во внимание

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0])

ARRAYELEMENTCOUNT(p + 1);

Это правильно оценивает:

(sizeof (p + 1) / sizeof (p + 1)[0]);

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


Это правильно; мой пример был плохим. Но это именно то, что должно произойти. Как я упоминал ранее, p + 1 будет в конечном итоге указывать на тип указателя и сделает недействительным весь макрос (как если бы вы пытались использовать макрос в функции с параметром указателя).

В конце дня, в этом конкретном экземпляре, ошибка на самом деле не имеет значения (поэтому я просто трачу время каждого, хазз!), Потому что у вас нет выражений с тип «массива». Но на самом деле вопрос о тонкостях оценки препроцессора, я думаю, очень важен.

14 голосов
/ 17 августа 2011

Для многомерных массивов это немного сложнее. Часто люди определяют явные макроконстанты, т.е.

#define g_rgDialogRows   2
#define g_rgDialogCols   7

static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{
    { " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },
    { " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};

Но эти константы можно оценить и во время компиляции с помощью sizeof :

#define rows_of_array(name)       \
    (sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \
    (sizeof(name[0]) / sizeof(name[0][0]))

static char* g_rgDialog[][7] = { /* ... */ };

assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);

Обратите внимание, что этот код работает на C и C ++. Для массивов с более чем двумя измерениями используйте

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])

и т. Д. До бесконечности.

13 голосов
/ 20 ноября 2015

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

int a[10];
size_t size_of_array = sizeof(a);      // Size of array a
int n = sizeof (a) / sizeof (a[0]);    // Number of elements in array a
size_t size_of_element = sizeof(a[0]); // Size of each element in array a                                          
                                       // Size of each element = size of type
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...