Основное использование массива в C? - PullRequest
3 голосов
/ 19 апреля 2011

Так вы, ребята, получаете размер массива в ANSI-C99? Кажется, что это неуклюжее происхождение от высшего языка.

int tests[7];
for (int i=0; i<sizeof(tests)/sizeof(int); i++) {
    tests[i] = rand();
}

Также эта ошибка сегментации.

int r = 10000000;
printf ("r: %i\n", r);
int tests[r];

запустите:

r: 10000000
Segmentation fault

10000000 ошибок сегмента, но 1000000 работает.

Как мне получить больше информации из этого? Что я должен проверять и как отладить что-то подобное? Есть ли предел для массивов C? Что такое ошибка сегментации?

Ответы [ 6 ]

3 голосов
/ 19 апреля 2011

Получить размер массива в C легко.Это даст вам размер массива в байтах.

sizeof(x)

Но я предполагаю, что вам нужно количество элементов, в этом случае это будет:

sizeof(x) / sizeof(x[0])

Вы можете написатьпростой макрос для этого:

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

Например:

int a[10];
int size_a = sizeof(a); /* size in bytes */
int numElm = NumElements(a); /* number of elements, here 10 */
2 голосов
/ 19 апреля 2011

Зачем рассчитывать размер?

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

Будучи в первую очередь программистом C ++, я скажу, что исторически константа часто определялась как значение enum или #define. В C это может быть скорее текущим, чем историческим - я не знаю, как текущий C обрабатывает «const».

Если вы действительно хотите рассчитать размер, определите макрос для этого. Может быть даже стандартный.

Причина segfault наиболее вероятна, потому что массив, который вы пытаетесь объявить, имеет размер около 40 мегабайт и объявлен как локальная переменная. Большинство операционных систем ограничивают размер стека. Держите ваш массив в куче или в глобальной памяти, и 40 мегабайт для одной переменной, вероятно, подойдут для большинства систем, хотя некоторые встроенные системы могут все еще плакать. В языке, подобном Java, все объекты находятся в куче, и в стеке хранятся только ссылки. Это простая и гибкая система, но зачастую гораздо менее эффективная, чем хранение данных в стеке (издержки на выделение кучи, предотвращаемая фрагментация кучи, накладные расходы на косвенный доступ ...).

1 голос
/ 19 апреля 2011

Массивы в C не знают, насколько они велики, поэтому да, вам нужно выполнить трюк sizeof array / sizeof array[0], чтобы получить количество элементов в массиве.

Что касается проблемы с segfault, я предполагаю, что вы превысили размер стека, пытаясь выделить 10000000 * sizeof int байт. Практическое правило заключается в том, что если вам требуется более нескольких сотен байтов, выделите его динамически, используя malloc или calloc, вместо того, чтобы пытаться создать большую переменную auto:

int r = 10000000;
int *tests = malloc(sizeof *test * r);

Обратите внимание, что вы можете трактовать tests , как если бы это был тип массива в большинстве случаев (т. Е. Вы можете добавить его в нижний индекс, передать его любой функции, которая ожидает массив и т. Д.) , но это не тип массива ; это тип указателя, поэтому трюк sizeof tests / sizeof tests[0] не сработает.

1 голос
/ 19 апреля 2011

Традиционно массив имеет статический размер.Таким образом, мы можем сделать

#define LEN 10
int arr[LEN];

, но не

int len;
scanf("%d", &len);
int arr[len]; // bad!

Поскольку мы знаем размер массива во время компиляции, получение размера массива имеет тенденцию к тривиальности.Нам не нужен sizeof, потому что мы можем выяснить размер, посмотрев наше объявление.

C ++ предоставляет массивы кучи, как в

int len;
scanf("%d", &len);
int *arr = new int[len];

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

0 голосов
/ 19 апреля 2011

Я подозреваю, что это из-за целочисленного переполнения. Попробуйте напечатать значение, используя printf:

printf("%d", 10000000);

Если он печатает отрицательное число - это проблема.

0 голосов
/ 19 апреля 2011

переполнение стека!Попробуйте выделить в куче, а не в стеке.

...