длина массива в C - PullRequest
       8

длина массива в C

10 голосов
/ 18 января 2010

Я написал функцию array_length так:

int array_length(int a[]){
    return sizeof(a)/sizeof(int);
}

Однако он возвращает 2, когда я сделал

unsigned int len = array_length(arr);
printf ("%i" , len);

где у меня

int arr[] = {3,4,5,6,1,7,2};
int * parr = arr;

Но когда я просто делаю

int k = sizeof(arr)/sizeof(int);
printf("%i", k);

в основной функции возвращает 7.

Как правильно написать функцию array_length и как ее использовать?

Ответы [ 14 ]

1 голос
/ 26 октября 2016

Я обнаружил, что это была ловушка, созданная нашим компилятором C! (Так это стандарт CPL? C99 или что-то еще?) Я написал следующий код в Visual Studio 2010 на платформе x86.

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

int main()
{
    int a[3] = { 0xa, 0xb, 0xc }; // Declare an array which include 3 items.
    int len = sizeof(a) / sizeof(a[0]); // And the variable len refer to the code like @Neil Chowdhury o_O
    int * pa0 = a; // Then i declared a pointer point to the first element to the source array a.
    int len2 = sizeof(a) / sizeof(pa0[0]); // Len2 refer to the same action like previous statement.
    int len3 = sizeof(a) / sizeof(pa0); // Len3 refer to a's size(one int's size)divide may be a int pointer's size.
    int len4 = sizeof(pa0); // Len4 is the size of int pointer pa0.
    int len5 = sizeof(a); // And len5 is the size of pa0, the same theory as previous stmt represented.
    int len6 = sizeof(a[0]); // Len6 equal to sizeof(int)
    int len7 = sizeof(pa0[0]); // Len7 equal to sizeof(int) too.
    return 0;
}

Затем я собрал их и показал код разборки. Результаты лайков:

    int a[3] = { 0xa, 0xb, 0xc };
00D13108  mov         dword ptr [ebp-14h],0Ah  
00D1310F  mov         dword ptr [ebp-10h],0Bh  
00D13116  mov         dword ptr [ebp-0Ch],0Ch  
    int len = sizeof(a) / sizeof(a[0]);
00D1311D  mov         dword ptr [ebp-20h],3  // caution!
    int * pa0 = a;
00D13124  lea         eax,[ebp-14h]  
00D13127  mov         dword ptr [ebp-2Ch],eax  
    int len2 = sizeof(a) / sizeof(pa0[0]);
00D1312A  mov         dword ptr [ebp-38h],3   // caution!
    int len3 = sizeof(a) / sizeof(pa0);
00D13131  mov         dword ptr [ebp-44h],3   // caution!
    int len4 = sizeof(pa0);
00D13138  mov         dword ptr [ebp-50h],4  
    int len5 = sizeof(a);
00D1313F  mov         dword ptr [ebp-5Ch],0Ch  
    int len6 = sizeof(a[0]);
00D13146  mov         dword ptr [ebp-68h],4  
    int len7 = sizeof(pa0[0]);
00D1314D  mov         dword ptr [ebp-74h],4  
    return 0;
00D13154  xor         eax,eax  

Итак, что? посмотрите на эти "осторожные" отмеченные линии! Как наш c-компилятор относился к нашему C-коду? Когда приходит указатель, особенно когда мы написали предложение вроде что-то = sizeof (один элемент массива) / sizeof (первый элемент этого массива) Компилятор разбирает наш синтаксис как номер массива! Это еще не закончено.


Я тоже протестировал "динамический массив". Массив, который выделяет malloc и т. Д.

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

int main()
{

    int * a = NULL;
    int len = 0;
    a = (int *) calloc(7, sizeof(int));
    len = sizeof(a) / sizeof(a[0]);
    return 0;
}

Сборка .. Разборка ...

    int * a = NULL;
013830FE  mov         dword ptr [a],0  
    int len = 0;
01383105  mov         dword ptr [len],0  
    a = (int *) calloc(7, sizeof(int)); 
0138310C  mov         esi,esp  
0138310E  push        4  
01383110  push        7  
01383112  call        dword ptr [__imp__calloc (13882CCh)]  
01383118  add         esp,8  
0138311B  cmp         esi,esp  
0138311D  call        @ILT+300(__RTC_CheckEsp) (1381131h)  
01383122  mov         dword ptr [a],eax  
    len = sizeof(a) / sizeof(a[0]);
01383125  mov         dword ptr [len],1  // Hey!
    return 0;
0138312C  xor         eax,eax  
}

Вы это видите? компилятор пропустил наш синтаксис в это время. Итак, вывод таков: Когда вы пишете предложение, особенно, как: что-то = sizeof (один элемент массива) / sizeof (первый элемент этого массива) Компилятор поймет и проанализирует наш код, и что-то подпишет емкость массива. Только если исходный массив является фиксированным массивом или массив уже объявил размер ранее. (В настоящее время размер константы может храниться в таблице переменных компилятора.) Это в основном как @rmn сказал. Вот что я нашел. Может быть бесполезным.

1 голос
/ 19 января 2010

Синтаксис "int a []", используемый в качестве аргумента функции, эквивалентен "int * a".

Этот синтаксис:

int arr [] = {3, 4,5,6,1,7,2};

Работает только во время компиляции.

Так что пока можно написать: int arr [] = {3,4,5,6,1,7,2};printf ("size =% d \ n", sizeof (arr));

Это будет работать только во время компиляции.

Один из способов обойти это - сделать динамические массивыи создайте свой собственный тип массива.

Например,

typedef struct array{
int length;
int *arr;
} array;

И используйте malloc, чтобы установить его размер.Вы можете заполнить его, используя elipses.

populate_array(array, ...);

например, затем вызвать populate_array (arr, 1,2,3,4,5,6);см. stdarg.

Однако, поскольку ваш компилятор C также вполне может быть компилятором C ++.Подумайте об использовании std :: vector.Тяжелая работа тогда сделана для вас.

1 голос
/ 19 января 2010

Ссылка на массив решит эту проблему, хотя я бы никогда не предложил использовать такую ​​вещь (поскольку она будет работать только в том случае, если вы всегда будете передавать по ссылке или использовать ее в области, в которой был определен массив):

#include <iostream>

template <typename Arrtype>
unsigned mysize (Arrtype (&arr)) {
 return sizeof(arr) / sizeof(arr[0]);
}

int main () {
 unsigned arr[13];
 std::cout << mysize(arr) << std::endl; // prints 13
}

Также упоминается здесь: http://cplusplus.co.il/2009/09/06/more-on-arrays/

Редактировать: Как предлагается в комментариях, другое возможное решение это:

template <typename T, unsigned N>
unsigned mysize(T (&)[N]) {
    return N;
} 
0 голосов
/ 06 апреля 2016

Это работает довольно хорошо:

int A[5] = {10, 20, 30, 40, 3};
int length = sizeof(A) / sizeof(A[0]);  // prints 5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...