2012-02-15 3 views
0

Счет возвращает непредсказуемые результаты. Иногда они правы. Иногда совершенно странно. Кто-нибудь может сказать мне, что не так?Длина массива с учетом аномалии

#include <stdio.h> 
int len(int[]); 

int main (int argc, const char * argv[]) 
{ 
    int a[]={1,2,3,4,5,6,7,8}; 
    int* i = a; 
    printf("length is %d",(len(i))); 
    return 0; 
} 

int len(int* a){ 
    int count = 0; 
    for (; *a!='\0'; a++) { 
     count++; 
    } 
    return count; 
} 
+2

Да. То, что вы пытаетесь сделать, по своей сути ошибочно. Вы не можете считать длины массивов в C. Если у вас есть _actual array_, вы можете использовать '#define ARRLEN (arr) (sizeof (arr)/sizeof (* arr))', но он не будет работать с указателями и поэтому на массивы передаются функции. –

ответ

3

Я думаю, что вы путаетесь между строками C (массивы char) и другими массивами. Это соглашение о том, что строки C заканчиваются нулевым символом ('\0'), но не все массивы (даже char массивы) заканчиваются таким образом.

Общее соглашение состоит в том, чтобы либо хранить длину массива где-то, либо использовать значение сторожевой части в конце массива. Это значение должно быть таким, которое не будет отображаться внутри массива - например, '\0' в строках, или -1 в массиве положительных целых чисел.

Кроме того, если вы знаете, что a является целочисленный массив (а не указатель на целочисленный массив), то вы можете использовать:

size_t length = sizeof(a)/sizeof(a[0]); 

Так что вы можете сделать:

int a[] = {1,2,3,4,5,6,7,8}; 
size_t length = sizeof(a)/sizeof(a[0]); 

// In this case, sizeof(a[0]) 
// is the same as sizeof(int), because it's an int array. 

Но вы не можете сделать:

int *a = malloc(sizeof(int) * 10); 
size_t length = sizeof(a)/sizeof(a[0]); // WRONG! 

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

Обратите внимание, что вы также не можете использовать это sizeof, чтобы прочитать размер массива, который был передан в функцию. Не имеет значения, будете ли вы объявлять свою функцию len(int *a) или - a будет указателем, потому что компилятор преобразует массивы в аргументы функции в указатель на их первый элемент.

+0

'int' для длины? \ * shudder \ * (И когда вы исправляете это до 'size_t', рассмотрите возможность изменения' sizeof (int) 'на' sizeof (a [0]) '.) –

+0

@ChrisLutz Упс, спасибо. Я использовал 'int' вместо' a [0] ', чтобы понять, что такое вычисление, но я думаю, что я должен выразить это словами. Обновлено :) –

7

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

Функция len(), которую вы пытаетесь написать, не может быть записана для общих массивов в C - определить размер динамического массива невозможно без использования (недокументированных, специфичных для платформы) внутренних блоков распределения памяти. Если это важно для вашего приложения, вы могли бы сделать это только в том случае, если бы вы могли явно добавить нуль в конце каждого массива.

1

Вы не можете рассчитывать такие массивы. Только строки завершаются нулем. Если вы хотите, чтобы это работало надежно, вам нужно добавить дополнительный элемент в массив, содержащий «\ 0». Но не забудьте вспомнить, что ваша длина не будет больше, чем истинная длина из-за этого '\ 0'

1

В отличие от строк, обычные массивы не заканчиваются нулевым байтом 0x00. Причиной использования строк является то, что массивы не имеют понятия длины; массивы - это просто непрерывные фрагменты памяти, вам нужно следить за длиной массивов.

Смежные вопросы