14

I want to make a FUNCTION which calculates size of passed array.

I will pass an Array as input and it should return its length. I want a Function

int ArraySize(int * Array   /* Or int Array[] */)
{
   /* Calculate Length of Array and Return it */

}

void main()
{
  int MyArray[8]={1,2,3,0,5};
  int length;

  length=ArraySize(MyArray);

  printf("Size of Array: %d",length);

}

Length should be 5 as it contains 5 elements though it's size is 8 (Even 8 will do but 5 would be excellent)

I tried this:

int ArraySize(int * Array)
{

  return (sizeof(Array)/sizeof(int));

}

This won't work as "sizeof(Array)" will retun size of Int Pointer. This "sizeof" thing works only if you are in same function.

Actually I am back to C after lots of days from C# So I can't remember (and Missing Array.Length())

Regards!

Swanand
  • 4,027
  • 10
  • 41
  • 69
  • 1
    Your array `MyArray` contains 8 elements. 5 of them have been explicitly initialized with 1, 2, 3, 0, and 5 respectively; the other 3 have been implicitly initialized with 0. – pmg Nov 12 '10 at 09:47
  • Yeah I know.... But is there any method to get the count 5? – Swanand Nov 12 '10 at 09:58

9 Answers9

34

You cannot calculate the size of an array when all you've got is a pointer.

The only way to make this "function-like" is to define a macro:

#define ARRAY_SIZE( array ) ( sizeof( array ) / sizeof( array[0] ) )

This comes with all the usual caveats of macros, of course.

Edit: (The comments below really belong into the answer...)

  1. You cannot determine the number of elements initialized within an array, unless you initialize all elements to an "invalid" value first and doing the counting of "valid" values manually. If your array has been defined as having 8 elements, for the compiler it has 8 elements, no matter whether you initialized only 5 of them.
  2. You cannot determine the size of an array within a function to which that array has been passed as parameter. Not directly, not through a macro, not in any way. You can only determine the size of an array in the scope it has been declared in.

The impossibility of determining the size of the array in a called function can be understood once you realize that sizeof() is a compile-time operator. It might look like a run-time function call, but it isn't: The compiler determines the size of the operands, and inserts them as constants.

In the scope the array is declared, the compiler has the information that it is actually an array, and how many elements it has.

In a function to which the array is passed, all the compiler sees is a pointer. (Consider that the function might be called with many different arrays, and remember that sizeof() is a compile-time operator.

You can switch to C++ and use <vector>. You can define a struct vector plus functions handling that, but it's not really comfortable:

#include <stdlib.h>

typedef struct
{
    int *  _data;
    size_t _size;
} int_vector;

int_vector * create_int_vector( size_t size )
{
    int_vector * _vec = malloc( sizeof( int_vector ) );
    if ( _vec != NULL )
    {
        _vec._size = size;
        _vec._data = (int *)malloc( size * sizeof( int ) );
    }
    return _vec;
}

void destroy_int_vector( int_vector * _vec )
{
    free( _vec->_data );
    free( _vec );
}

int main()
{
    int_vector * myVector = create_int_vector( 8 );
    if ( myVector != NULL && myVector->_data != NULL )
    {
        myVector->_data[0] = ...;
        destroy_int_vector( myVector );
    }
    else if ( myVector != NULL )
    {
        free( myVector );
    }
    return 0;
}

Bottom line: C arrays are limited. You cannot calculate their length in a sub-function, period. You have to code your way around that limitation, or use a different language (like C++).

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • Thanks! This is good but I would be more happy with Function! – Swanand Nov 12 '10 at 09:08
  • @Swanand Purankar: I can understand that, but it is just plain impossible to do in C. – DevSolar Nov 12 '10 at 12:07
  • @Swanand Purankar: I just saw your comment under your question... note that this macro will **not** give you a 5 in your example, but 8. There is no way for C to tell which / how many array elements have actually been assigned (unless you manually insert special values for uninitialized elements and do likewise manual counting of non-special values). C itself can only tell you the overall size of the array. – DevSolar Nov 12 '10 at 15:21
  • @DevSolar: I tried this Macro but the problem is I can not use this Macro in Functions to which an array is passed by pointer! Any Help?? – Swanand Nov 15 '10 at 05:03
  • @DevSolar: Thank you again!! I have to use C for my application so as you said, I have to Code my way around Limitations! Thanks a lot!! – Swanand Nov 15 '10 at 11:05
  • You should add more parenthesis around your macro #define array_length(array) (sizeof(array) / sizeof(array[0])) Otherwise you might get some strange results when use in the context of a bigger equation. – superlogical Dec 18 '16 at 07:25
12

You can't do this once the array has decayed to a pointer - you'll always get the pointer size.

What you need to do is either:

  • use a sentinel value if possible, like NULL for pointers or -1 for positive numbers.
  • calculate it when it's still an array, and pass that size to any functions.
  • same as above but using funky macro magic, something like:
    #define arrSz(a) (sizeof(a)/sizeof(*a)).
  • create your own abstract data type which maintains the length as an item in a structure, so that you have a way of getting your Array.length().
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Its not compulsary to pass the pointer.... Any method by Passing Array would work. – Swanand Nov 12 '10 at 09:08
  • 6
    @SwanandPurankar: Not sure what exactly you mean, but in C, `void foo(int[] arr)` and `void foo(int *ptr)` are one and the same. Thus,an array passed to a function *always* decays to a pointer (to the array's first element). – mk12 Aug 09 '12 at 20:29
3

What you ask for simply can't be done.

At run time, the only information made available to the program about an array is the address of its first element. Even the size of the elements is only inferred from the type context in which the array is used.

JeremyP
  • 84,577
  • 15
  • 123
  • 161
2

In C you can't because array decays into a pointer(to the first element) when passed to a function.

However in C++ you can use Template Argument Deduction to achieve the same.

Community
  • 1
  • 1
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
1
int getArraySize(void *x)
{
    char *p = (char *)x;
    char i = 0;
    char dynamic_char = 0xfd;
    char static_char = 0xcc;

    while(1)
    {
        if(p[i]==dynamic_char || p[i]==static_char)
            break;
        i++;
    }
    return i;
}

int _tmain(int argc, _TCHAR* argv[])
{   
    void *ptr = NULL;
    int array[]={1,2,3,4,5,6,7,8,9,0};
    char *str;
    int totalBytes;

    ptr = (char *)malloc(sizeof(int)*3);
    str = (char *)malloc(10);

    totalBytes = getArraySize(ptr);
    printf("ptr = total bytes = %d and allocated count = %d\n",totalBytes,(totalBytes/sizeof(int)));

    totalBytes = getArraySize(array);
    printf("array = total bytes = %d and allocated count = %d\n",totalBytes,(totalBytes/sizeof(int)));

    totalBytes = getArraySize(str);
    printf("str = total bytes = %d and allocated count = %d\n",totalBytes,(totalBytes/sizeof(char)));
    return 0;
}
  • 1
    Can you explain Why "0xfd" and "0xcc"?? – Swanand Oct 26 '12 at 13:18
  • This only works in MS Visual C++ debugging mode, and only (since `i` is a char) for sizes < 256 where no element is a legit `0xfd`. Down-voting since the answer does not work in general, and does not even document when it may or may not work. See [this answer](http://stackoverflow.com/a/127404/15472) for some magical numbers used by Visual C++ – tucuxi Dec 16 '15 at 20:43
1

You need to either pass the length as an additional parameter (like strncpy does) or zero-terminate the array (like strcpy does).

Small variations of these techniques exist, like bundling the length with the pointer in its own class, or using a different marker for the length of the array, but these are basically your only choices.

Blindy
  • 65,249
  • 10
  • 91
  • 131
1

Not possible. You need to pass the size of the array from the function, you're calling this function from. When you pass the array to the function, only the starting address is passed not the whole size and when you calculate the size of the array, Compiler doesn't know How much size/memory, this pointer has been allocated by the compiler. So, final call is, you need to pass the array size while you're calling that function.

Ajay Kumar
  • 586
  • 5
  • 21
0

Is is very late. But I found a workaround for this problem. I know it is not the proper solution but can work if you don't want to traverse a whole array of integers.

checking '\0' will not work here

First, put any character in array at the time of initialization

for(i=0;i<1000;i++)
array[i]='x';

then after passing values check for 'x'

i=0;
while(array[i]!='x')
{
i++;
return i;
}

let me know if it is of any use.

-4

Size of an arry in C is :

int a[]={10,2,22,31,1,2,44,21,5,8};

printf("Size : %d",sizeof(a)/sizeof(int));
zero323
  • 322,348
  • 103
  • 959
  • 935
Md Shahriar
  • 2,072
  • 22
  • 11
  • 1
    once you pass `a` to a function as a parameter, that trick does not work, since `sizeof()` is a compile-time function. – tucuxi Dec 16 '15 at 20:45
  • 2
    This does not answer the question. Since there are already answers that do, I would recommend you delete this one. If anything, this proposed answer will identify you as a developer that is lacking event the most basic skills. – IInspectable Dec 16 '15 at 23:06
  • @Md-Shahriar I was looking for a function which will do this task. – Swanand Dec 17 '15 at 04:20