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

StackOverflow https://stackoverflow.com/questions/37538

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

Резюме:

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);

Другие советы

Тот Самый 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

Стоит отметить, что 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 на реальном объекте, когда он у вас есть, а не на типе, поскольку тогда вам не нужно беспокоиться о том, чтобы сделать ошибку и указать неверный тип.

Например, скажем, у вас есть функция, которая выводит некоторые данные в виде потока байтов, например, по сети. Давайте вызовем функцию 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) то, что каждый использует, оценивает неправильно.На самом деле это просто деликатный вопрос, потому что у вас не может быть выражений, которые приводят к типу 'array'.

/* 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 завершится как тип указателя и сделает недействительным весь макрос (точно так же, как если бы вы попытались использовать макрос в функции с параметром указателя).

В конце концов, в этом конкретный например, ошибка на самом деле не имеет значения (так что я просто трачу время каждого;ура!), потому что у вас нет выражений с типом 'array'.Но на самом деле момент, касающийся тонкостей оценки препроцессора, я считаю важным.

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

#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 не сохраняют свой размер.Поэтому рекомендуется сохранять длину массива в отдельной переменной /const и передавать ее всякий раз, когда вы передаете массив, то есть:

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

Вам всегда следует избегать собственных массивов (если только вы не можете этого сделать, и в этом случае будьте осторожны).Если вы пишете на C ++, используйте STL's 'векторный' контейнер."По сравнению с массивами они обеспечивают почти такую же производительность", и они гораздо более полезны!

// vector is a template, the <int> means it is a vector of ints
vector<int> 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/

@ Magnus: стандарт определяет sizeof как число байтов в объекте, а sizeof (char) всегда равен единице. Количество битов в байте зависит от конкретной реализации.

Редактировать: стандартный раздел ANSI C ++ 5.3.3 Sizeof:

  

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

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

  

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

  

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

Википедия не права, Скизз прав. 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 <stdio.h>
#include <string.h>
/*
#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;

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

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

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);

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

#include<stdio.h>
#include<stdlib.h>
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
int a[10];
int size = (*(&a+1)-a) ;

Подробнее см. здесь а также здесь .

Пример

#include <stdio.h>

int main() {
    int size;
    scanf("%d", &size);
    int array[size];
    printf("%d\n", (int) (sizeof(array) / sizeof(int)));
    printf("%d\n", (int) (sizeof(array) / sizeof(array[0])));
    return 0;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top