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

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

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

Управляющее резюме:

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

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

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

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

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

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

и получите правильный ответ (68/4 = 17), но если тип измененного, у вас будет неприятная ошибка, если вы забыли изменить 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); 

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

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

Контрольная работа:

 #include  #include  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 

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

 int a[10]; int* p = a; assert(sizeof(a) / sizeof(a[0]) == 10); assert(sizeof(p) == sizeof(int*)); assert(sizeof(*p) == sizeof(int)); 

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

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

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

 int myArray[10]; 

Вы можете найти количество элементов с таким кодом:

 size_t n = sizeof myArray / sizeof *myArray; 

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

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

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

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

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

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

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

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

 send(&foo, sizeof foo); 

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

 int size = (&arr)[1] - arr; 

Ознакомьтесь с этой ссылкой для объяснения

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

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

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

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

 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 (имя массива) является указателем.

Макрос 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]); 

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


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

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

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

 #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]) 

и т.д., до бесконечности.

Размер массива в 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 
 sizeof(array) / sizeof(array[0]) 
 #define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0])) 

«вы ввели тонкий способ стрелять себе в ногу»

C ‘native’ массивы не сохраняют свой размер. Поэтому рекомендуется сохранять длину массива в отдельной переменной / const и передавать ее всякий раз, когда вы передаете массив, то есть:

 #define MY_ARRAY_LENGTH 15 int myArray[MY_ARRAY_LENGTH]; 

Вы ДОЛЖНЫ всегда избегать встроенных массивов (если вы не можете, и в этом случае, заметьте свою ногу). Если вы пишете C ++, используйте контейнер STL ‘vector’. «По сравнению с массивами они обеспечивают почти ту же производительность», и они гораздо полезнее!

 // vector is a template, the  means it is a vector of ints vector numbers; // push_back() puts a new value at the end (or back) of the vector for (int i = 0; i < 10; i++) numbers.push_back(i); // Determine the size of the array cout << numbers.size(); 

См .: http://www.cplusplus.com/reference/stl/vector/

@ Магнус: стандарт определяет sizeof как уступающий количеству байтов в объекте, а sizeof (char) всегда один. Количество бит в байте является специфичным для реализации.

Изменить: Стандартная секция ANSI C ++. 5.3.3. Размер:

Оператор sizeof дает количество байтов в представлении объекта своего операнда. […] sizeof (char), sizeof (signed char) и sizeof (unsigned char) равны 1; результат sizeof, применяемый к любому другому фундаментальному типу, определяется реализацией.

Раздел 1.6. Модель памяти C ++:

Основным блоком памяти в модели памяти C ++ является байт. Байт, по меньшей мере, достаточно большой, чтобы содержать любой элемент базового набора символов исполнения и состоит из непрерывной последовательности бит, число которой определяется реализацией.

@Skizz: Я уверен, что я прав, хотя лучший «источник», который я могу вам дать в данный момент, – это Википедия, из статьи о sizeof:

Википедия ошибается, Skizz прав. sizeof (char) равен 1, по определению.

Я имею в виду, просто внимательно прочитайте статью в Википедии, чтобы понять, что это неправильно. «кратные символы». sizeof(char) никогда не может быть чем-то другим, кроме «1». Если бы это было, скажем, 2, это означало бы, что sizeof(char) был вдвое больше размера char!

Если вы действительно хотите сделать это, чтобы передать свой массив, я предлагаю реализовать структуру для хранения указателя на тип, в котором вы хотите получить массив и целое число, представляющее размер массива. Затем вы можете передать это своим функциям. Просто присвойте значение переменной массива (указатель на первый элемент) этому указателю. Затем вы можете перейти в Array.arr[i] чтобы получить i-й элемент и использовать Array.size для получения количества элементов в массиве.

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

 /* Absolutely no one should use this... By the time you're done implementing it you'll wish you just passed around an array and size to your functions */ /* This is a static implementation. You can get a dynamic implementation and cut out the array in main by using the stdlib memory allocation methods, but it will work much slower since it will store your array on the heap */ #include  #include  /* #include "MyTypeArray.h" */ /* MyTypeArray.h #ifndef MYTYPE_ARRAY #define MYTYPE_ARRAY */ typedef struct MyType { int age; char name[20]; } MyType; typedef struct MyTypeArray { int size; MyType *arr; } MyTypeArray; MyType new_MyType(int age, char *name); MyTypeArray newMyTypeArray(int size, MyType *first); /* #endif End MyTypeArray.h */ /* MyTypeArray.c */ MyType new_MyType(int age, char *name) { MyType d; d.age = age; strcpy(d.name, name); return d; } MyTypeArray new_MyTypeArray(int size, MyType *first) { MyTypeArray d; d.size = size; d.arr = first; return d; } /* End MyTypeArray.c */ void print_MyType_names(MyTypeArray d) { int i; for (i = 0; i < d.size; i++) { printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age); } } int main() { /* First create an array on the stack to store our elements in. Note we could create an empty array with a size instead and set the elements later. */ MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")}; /* Now create a "MyTypeArray" which will use the array we just created internally. Really it will just store the value of the pointer "arr". Here we are manually setting the size. You can use the sizeof trick here instead if you're sure it will work with your compiler. */ MyTypeArray array = new_MyTypeArray(2, arr); /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */ print_MyType_names(array); return 0; } 

Лучший способ – сохранить эту информацию, например, в структуре:

 typedef struct { int *array; int elements; } list_s; 

Внедрите все необходимые функции, такие как создание, уничтожение, проверка равенства и все остальное, что вам нужно. Его легче передать в качестве параметра.

Вы можете использовать оператор & . Вот исходный код:

 #include #include int main(){ int a[10]; int *p; printf("%p\n", (void *)a); printf("%p\n", (void *)(&a+1)); printf("---- diff----\n"); printf("%zu\n", sizeof(a[0])); printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0]))); return 0; }; 

Вот пример вывода

 1549216672 1549216712 ---- diff---- 4 The size of array a is 10 

Функция sizeof возвращает количество байтов, которое используется вашим массивом в памяти. Если вы хотите вычислить количество элементов в вашем массиве, вы должны разделить это число с типом переменной sizeof массива. Скажем, int array[10]; , если целочисленное целое число переменной на вашем компьютере равно 32 бит (или 4 байта), чтобы получить размер вашего массива, вы должны сделать следующее:

 int array[10]; int sizeOfArray = sizeof(array)/sizeof(int); 
 int a[10]; int size = (*(&a+1)-a) ; 

для получения дополнительной информации: https://aticleworld.com/how-to-find-sizeof-array-in-cc-without-using-sizeof/https://www.geeksforgeeks.org/how-to-find-size- из-массива-в-CC-без-помощи-SizeOf-оператор /

Использование:

 int a=[10] = {1, 2, 3, 4, 5}; int n = sizeof(a); printf("%d", n); 

Вывод:

 5 

Причина: вычисляет количество элементов, хранящихся в массиве, а не количество свободных пространств, выделенных для него.

  • Когда Fragment заменяется и помещается в задний стек (или удаляется), он остается в памяти?
  • EditText вызывает утечку памяти
  • Как очистить память, чтобы предотвратить «ошибку из памяти» в excel vba?
  • Создание утечки памяти с помощью Java
  • Пустое пространство Java из памяти
  • что использует MemoryFile в android
  • Слабые справочные преимущества
  • интересное OutOfMemoryException с StringBuilder
  • Создайте функцию обертки для malloc и освободите ее на C
  • Поиск диапазона адресов сегмента данных
  • OpenCV для использования в буферах памяти или указателях файлов
  • Давайте будем гением компьютера.