Executive summary:
int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
Full answer:
To determine the size of your array in bytes, you can use the sizeof
operator:
int a[17];
size_t n = sizeof(a);
On my computer, ints are 4 bytes long, so n is 68.
To determine the number of elements in the array, we can divide the total size of the array by the size of the array element. You could do this with the type, like this:
int a[17];
size_t n = sizeof(a) / sizeof(int);
and get the proper answer (68 / 4 = 17), but if the type of
a changed you would have a nasty bug if you forgot to change
the sizeof(int) as well.
So the preferred divisor is sizeof(a[0]) or the equivalent sizeof(*a), the size of the first element of the array.
int a[17];
size_t n = sizeof(a) / sizeof(a[0]);
Another advantage is that you can now easily parameterize the array name in a macro and get:
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
int a[17];
size_t n = NELEMS(a);
Answer from Mark Harrison on Stack OverflowExecutive summary:
int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
Full answer:
To determine the size of your array in bytes, you can use the sizeof
operator:
int a[17];
size_t n = sizeof(a);
On my computer, ints are 4 bytes long, so n is 68.
To determine the number of elements in the array, we can divide the total size of the array by the size of the array element. You could do this with the type, like this:
int a[17];
size_t n = sizeof(a) / sizeof(int);
and get the proper answer (68 / 4 = 17), but if the type of
a changed you would have a nasty bug if you forgot to change
the sizeof(int) as well.
So the preferred divisor is sizeof(a[0]) or the equivalent sizeof(*a), the size of the first element of the array.
int a[17];
size_t n = sizeof(a) / sizeof(a[0]);
Another advantage is that you can now easily parameterize the array name in a macro and get:
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
int a[17];
size_t n = NELEMS(a);
The sizeof way is the right way iff you are dealing with arrays not received as parameters. An array sent as a parameter to a function is treated as a pointer, so sizeof will return the pointer's size, instead of the array's.
Thus, inside functions this method does not work. Instead, always pass an additional parameter size_t size indicating the number of elements in the array.
Test:
#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]) ));
}
Output (in a 64-bit Linux OS):
sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2
Output (in a 32-bit windows OS):
sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
C Program Length of Array
Why do C arrays not keep track of their length? - Software Engineering Stack Exchange
Calculate Length of Array in C by Using Function - Stack Overflow
How to find the length of an array
How do you find the length of an array in C?
What is the length of an empty array in C?
Can I use sizeof() to get the length of an array inside a function?
Videos
The following code prints 40, but I expect the output to be 10. Any ideas why?
C arrays do keep track of their length, as the array length is a static property:
int xs[42]; /* a 42-element array */
You can't usually query this length, but you don't need to because it's static anyway – just declare a macro XS_LENGTH for the length, and you're done.
The more important issue is that C arrays implicitly degrade into pointers, e.g. when passed to a function. This does make some sense, and allows for some nice low-level tricks, but it loses the information about the length of the array. So a better question would be why C was designed with this implicit degradation to pointers.
Another matter is that pointers need no storage except the memory address itself. C allows us to cast integers to pointers, pointers to other pointers, and to treat pointers as if they were arrays. While doing this, C is not insane enough to fabricate some array length into existence, but seems to trust in the Spiderman motto: with great power the programmer will hopefully fulfill the great responsibility of keeping track of lengths and overflows.
A lot of this had to do with the computers available at the time. Not only did the compiled program have to run on a limited resource computer, but, perhaps more importantly, the compiler itself had to run on these machines. At the time Thompson developed C, he was using a PDP-7, with 8k of RAM. Complex language features that didn't have an immediate analog on the actual machine code were simply not included in the language.
A careful read through the history of C yields more understanding into the above, but it wasn't entirely a result of the machine limitations they had:
Moreover, the language (C) shows considerable power to describe important concepts, for example, vectors whose length varies at run time, with only a few basic rules and conventions. ... It is interesting to compare C's approach with that of two nearly contemporaneous languages, Algol 68 and Pascal [Jensen 74]. Arrays in Algol 68 either have fixed bounds, or are `flexible:' considerable mechanism is required both in the language definition, and in compilers, to accommodate flexible arrays (and not all compilers fully implement them.) Original Pascal had only fixed-sized arrays and strings, and this proved confining [Kernighan 81].
C arrays are inherently more powerful. Adding bounds to them restricts what the programmer can use them for. Such restrictions may be useful for programmers, but necessarily are also limiting.
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...)
- 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.
- 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++).
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().