Length of array in function argument - c

This is well known code to compute array length in C:
sizeof(array)/sizeof(type)
But I can't seem to find out the length of the array passed as an argument to a function:
#include <stdio.h>
int length(const char* array[]) {
return sizeof(array)/sizeof(char*);
}
int main() {
const char* friends[] = { "John", "Jack", "Jim" };
printf("%d %d", sizeof(friends)/sizeof(char*), length(friends)); // 3 1
}
I assume that array is copied by value to the function argument as constant pointer and reference to it should solve this, but this declaration is not valid:
int length(const char**& array);
I find passing the array length as second argument to be redundant information, but why is the standard declaration of main like this:
int main(int argc, char** argv);
Please explain if it is possible to find out the array length in function argument, and if so, why is there the redundancy in main.

sizeof only works to find the length of the array if you apply it to the original array.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
However, by the time the array decays into a pointer, sizeof will give the size of the pointer and not of the array.
int a[5];
int * p = a;
sizeof(p); // :(
As you have already smartly pointed out main receives the length of the array as an argument (argc). Yes, this is out of necessity and is not redundant. (Well, it is kind of reduntant since argv is conveniently terminated by a null pointer but I digress)
There is some reasoning as to why this would take place. How could we make things so that a C array also knows its length?
A first idea would be not having arrays decaying into pointers when they are passed to a function and continuing to keep the array length in the type system. The bad thing about this is that you would need to have a separate function for every possible array length and doing so is not a good idea. (Pascal did this and some people think this is one of the reasons it "lost" to C)
A second idea is storing the array length next to the array, just like any modern programming language does:
a -> [5];[0,0,0,0,0]
But then you are just creating an invisible struct behind the scenes and the C philosophy does not approve of this kind of overhead. That said, creating such a struct yourself is often a good idea for some sorts of problems:
struct {
size_t length;
int * elements;
}
Another thing you can think about is how strings in C are null terminated instead of storing a length (as in Pascal). To store a length without worrying about limits need a whopping four bytes, an unimaginably expensive amount (at least back then). One could wonder if arrays could be also null terminated like that but then how would you allow the array to store a null?

The array decays to a pointer when passed.
Section 6.4 of the C FAQ covers this very well and provides the K&R references etc.
That aside, imagine it were possible for the function to know the size of the memory allocated in a pointer. You could call the function two or more times, each time with different input arrays that were potentially different lengths; the length would therefore have to be passed in as a secret hidden variable somehow. And then consider if you passed in an offset into another array, or an array allocated on the heap (malloc and all being library functions - something the compiler links to, rather than sees and reasons about the body of).
Its getting difficult to imagine how this might work without some behind-the-scenes slice objects and such right?
Symbian did have a AllocSize() function that returned the size of an allocation with malloc(); this only worked for the literal pointer returned by the malloc, and you'd get gobbledygook or a crash if you asked it to know the size of an invalid pointer or a pointer offset from one.
You don't want to believe its not possible, but it genuinely isn't. The only way to know the length of something passed into a function is to track the length yourself and pass it in yourself as a separate explicit parameter.

As stated by #Will, the decay happens during the parameter passing. One way to get around it is to pass the number of elements. To add onto this, you may find the _countof() macro useful - it does the equivalent of what you've done ;)

First, a better usage to compute number of elements when the actual array declaration is in scope is:
sizeof array / sizeof array[0]
This way you don't repeat the type name, which of course could change in the declaration and make you end up with an incorrect length computation. This is a typical case of don't repeat yourself.
Second, as a minor point, please note that sizeof is not a function, so the expression above doesn't need any parenthesis around the argument to sizeof.
Third, C doesn't have references so your usage of & in a declaration won't work.
I agree that the proper C solution is to pass the length (using the size_t type) as a separate argument, and use sizeof at the place the call is being made if the argument is a "real" array.
Note that often you work with memory returned by e.g. malloc(), and in those cases you never have a "true" array to compute the size off of, so designing the function to use an element count is more flexible.

Regarding int main():
According to the Standard, argv points to a NULL-terminated array (of pointers to null-terminated strings). (5.1.2.2.1:1).
That is, argv = (char **){ argv[0], ..., argv[argc - 1], 0 };.
Hence, size calculation is performed by a function which is a trivial modification of strlen().
argc is only there to make argv length calculation O(1).
The count-until-NULL method will NOT work for generic array input. You will need to manually specify size as a second argument.

This is a old question, and the OP seems to mix C++ and C in his intends/examples. In C, when you pass a array to a function, it's decayed to pointer. So, there is no way to pass the array size except by using a second argument in your function that stores the array size:
void func(int A[])
// should be instead: void func(int * A, const size_t elemCountInA)
They are very few cases, where you don't need this, like when you're using multidimensional arrays:
void func(int A[3][whatever here]) // That's almost as if read "int* A[3]"
Using the array notation in a function signature is still useful, for the developer, as it might be an help to tell how many elements your functions expects. For example:
void vec_add(float out[3], float in0[3], float in1[3])
is easier to understand than this one (although, nothing prevent accessing the 4th element in the function in both functions):
void vec_add(float * out, float * in0, float * in1)
If you were to use C++, then you can actually capture the array size and get what you expect:
template <size_t N>
void vec_add(float (&out)[N], float (&in0)[N], float (&in1)[N])
{
for (size_t i = 0; i < N; i++)
out[i] = in0[i] + in1[i];
}
In that case, the compiler will ensure that you're not adding a 4D vector with a 2D vector (which is not possible in C without passing the dimension of each dimension as arguments of the function). There will be as many instance of the vec_add function as the number of dimensions used for your vectors.

int arsize(int st1[]) {
int i = 0;
for (i; !(st1[i] & (1 << 30)); i++);
return i;
}
This works for me :)

length of an array(type int) with sizeof:
sizeof(array)/sizeof(int)

Best example is here
thanks #define SIZE 10
void size(int arr[SIZE])
{
printf("size of array is:%d\n",sizeof(arr));
}
int main()
{
int arr[SIZE];
size(arr);
return 0;
}

Related

Why do C command line arguments include argc? [duplicate]

This is well known code to compute array length in C:
sizeof(array)/sizeof(type)
But I can't seem to find out the length of the array passed as an argument to a function:
#include <stdio.h>
int length(const char* array[]) {
return sizeof(array)/sizeof(char*);
}
int main() {
const char* friends[] = { "John", "Jack", "Jim" };
printf("%d %d", sizeof(friends)/sizeof(char*), length(friends)); // 3 1
}
I assume that array is copied by value to the function argument as constant pointer and reference to it should solve this, but this declaration is not valid:
int length(const char**& array);
I find passing the array length as second argument to be redundant information, but why is the standard declaration of main like this:
int main(int argc, char** argv);
Please explain if it is possible to find out the array length in function argument, and if so, why is there the redundancy in main.
sizeof only works to find the length of the array if you apply it to the original array.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
However, by the time the array decays into a pointer, sizeof will give the size of the pointer and not of the array.
int a[5];
int * p = a;
sizeof(p); // :(
As you have already smartly pointed out main receives the length of the array as an argument (argc). Yes, this is out of necessity and is not redundant. (Well, it is kind of reduntant since argv is conveniently terminated by a null pointer but I digress)
There is some reasoning as to why this would take place. How could we make things so that a C array also knows its length?
A first idea would be not having arrays decaying into pointers when they are passed to a function and continuing to keep the array length in the type system. The bad thing about this is that you would need to have a separate function for every possible array length and doing so is not a good idea. (Pascal did this and some people think this is one of the reasons it "lost" to C)
A second idea is storing the array length next to the array, just like any modern programming language does:
a -> [5];[0,0,0,0,0]
But then you are just creating an invisible struct behind the scenes and the C philosophy does not approve of this kind of overhead. That said, creating such a struct yourself is often a good idea for some sorts of problems:
struct {
size_t length;
int * elements;
}
Another thing you can think about is how strings in C are null terminated instead of storing a length (as in Pascal). To store a length without worrying about limits need a whopping four bytes, an unimaginably expensive amount (at least back then). One could wonder if arrays could be also null terminated like that but then how would you allow the array to store a null?
The array decays to a pointer when passed.
Section 6.4 of the C FAQ covers this very well and provides the K&R references etc.
That aside, imagine it were possible for the function to know the size of the memory allocated in a pointer. You could call the function two or more times, each time with different input arrays that were potentially different lengths; the length would therefore have to be passed in as a secret hidden variable somehow. And then consider if you passed in an offset into another array, or an array allocated on the heap (malloc and all being library functions - something the compiler links to, rather than sees and reasons about the body of).
Its getting difficult to imagine how this might work without some behind-the-scenes slice objects and such right?
Symbian did have a AllocSize() function that returned the size of an allocation with malloc(); this only worked for the literal pointer returned by the malloc, and you'd get gobbledygook or a crash if you asked it to know the size of an invalid pointer or a pointer offset from one.
You don't want to believe its not possible, but it genuinely isn't. The only way to know the length of something passed into a function is to track the length yourself and pass it in yourself as a separate explicit parameter.
As stated by #Will, the decay happens during the parameter passing. One way to get around it is to pass the number of elements. To add onto this, you may find the _countof() macro useful - it does the equivalent of what you've done ;)
First, a better usage to compute number of elements when the actual array declaration is in scope is:
sizeof array / sizeof array[0]
This way you don't repeat the type name, which of course could change in the declaration and make you end up with an incorrect length computation. This is a typical case of don't repeat yourself.
Second, as a minor point, please note that sizeof is not a function, so the expression above doesn't need any parenthesis around the argument to sizeof.
Third, C doesn't have references so your usage of & in a declaration won't work.
I agree that the proper C solution is to pass the length (using the size_t type) as a separate argument, and use sizeof at the place the call is being made if the argument is a "real" array.
Note that often you work with memory returned by e.g. malloc(), and in those cases you never have a "true" array to compute the size off of, so designing the function to use an element count is more flexible.
Regarding int main():
According to the Standard, argv points to a NULL-terminated array (of pointers to null-terminated strings). (5.1.2.2.1:1).
That is, argv = (char **){ argv[0], ..., argv[argc - 1], 0 };.
Hence, size calculation is performed by a function which is a trivial modification of strlen().
argc is only there to make argv length calculation O(1).
The count-until-NULL method will NOT work for generic array input. You will need to manually specify size as a second argument.
This is a old question, and the OP seems to mix C++ and C in his intends/examples. In C, when you pass a array to a function, it's decayed to pointer. So, there is no way to pass the array size except by using a second argument in your function that stores the array size:
void func(int A[])
// should be instead: void func(int * A, const size_t elemCountInA)
They are very few cases, where you don't need this, like when you're using multidimensional arrays:
void func(int A[3][whatever here]) // That's almost as if read "int* A[3]"
Using the array notation in a function signature is still useful, for the developer, as it might be an help to tell how many elements your functions expects. For example:
void vec_add(float out[3], float in0[3], float in1[3])
is easier to understand than this one (although, nothing prevent accessing the 4th element in the function in both functions):
void vec_add(float * out, float * in0, float * in1)
If you were to use C++, then you can actually capture the array size and get what you expect:
template <size_t N>
void vec_add(float (&out)[N], float (&in0)[N], float (&in1)[N])
{
for (size_t i = 0; i < N; i++)
out[i] = in0[i] + in1[i];
}
In that case, the compiler will ensure that you're not adding a 4D vector with a 2D vector (which is not possible in C without passing the dimension of each dimension as arguments of the function). There will be as many instance of the vec_add function as the number of dimensions used for your vectors.
int arsize(int st1[]) {
int i = 0;
for (i; !(st1[i] & (1 << 30)); i++);
return i;
}
This works for me :)
length of an array(type int) with sizeof:
sizeof(array)/sizeof(int)
Best example is here
thanks #define SIZE 10
void size(int arr[SIZE])
{
printf("size of array is:%d\n",sizeof(arr));
}
int main()
{
int arr[SIZE];
size(arr);
return 0;
}

C: get sizeof typedef struct array inside of function when passed as parameter [duplicate]

This is well known code to compute array length in C:
sizeof(array)/sizeof(type)
But I can't seem to find out the length of the array passed as an argument to a function:
#include <stdio.h>
int length(const char* array[]) {
return sizeof(array)/sizeof(char*);
}
int main() {
const char* friends[] = { "John", "Jack", "Jim" };
printf("%d %d", sizeof(friends)/sizeof(char*), length(friends)); // 3 1
}
I assume that array is copied by value to the function argument as constant pointer and reference to it should solve this, but this declaration is not valid:
int length(const char**& array);
I find passing the array length as second argument to be redundant information, but why is the standard declaration of main like this:
int main(int argc, char** argv);
Please explain if it is possible to find out the array length in function argument, and if so, why is there the redundancy in main.
sizeof only works to find the length of the array if you apply it to the original array.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
However, by the time the array decays into a pointer, sizeof will give the size of the pointer and not of the array.
int a[5];
int * p = a;
sizeof(p); // :(
As you have already smartly pointed out main receives the length of the array as an argument (argc). Yes, this is out of necessity and is not redundant. (Well, it is kind of reduntant since argv is conveniently terminated by a null pointer but I digress)
There is some reasoning as to why this would take place. How could we make things so that a C array also knows its length?
A first idea would be not having arrays decaying into pointers when they are passed to a function and continuing to keep the array length in the type system. The bad thing about this is that you would need to have a separate function for every possible array length and doing so is not a good idea. (Pascal did this and some people think this is one of the reasons it "lost" to C)
A second idea is storing the array length next to the array, just like any modern programming language does:
a -> [5];[0,0,0,0,0]
But then you are just creating an invisible struct behind the scenes and the C philosophy does not approve of this kind of overhead. That said, creating such a struct yourself is often a good idea for some sorts of problems:
struct {
size_t length;
int * elements;
}
Another thing you can think about is how strings in C are null terminated instead of storing a length (as in Pascal). To store a length without worrying about limits need a whopping four bytes, an unimaginably expensive amount (at least back then). One could wonder if arrays could be also null terminated like that but then how would you allow the array to store a null?
The array decays to a pointer when passed.
Section 6.4 of the C FAQ covers this very well and provides the K&R references etc.
That aside, imagine it were possible for the function to know the size of the memory allocated in a pointer. You could call the function two or more times, each time with different input arrays that were potentially different lengths; the length would therefore have to be passed in as a secret hidden variable somehow. And then consider if you passed in an offset into another array, or an array allocated on the heap (malloc and all being library functions - something the compiler links to, rather than sees and reasons about the body of).
Its getting difficult to imagine how this might work without some behind-the-scenes slice objects and such right?
Symbian did have a AllocSize() function that returned the size of an allocation with malloc(); this only worked for the literal pointer returned by the malloc, and you'd get gobbledygook or a crash if you asked it to know the size of an invalid pointer or a pointer offset from one.
You don't want to believe its not possible, but it genuinely isn't. The only way to know the length of something passed into a function is to track the length yourself and pass it in yourself as a separate explicit parameter.
As stated by #Will, the decay happens during the parameter passing. One way to get around it is to pass the number of elements. To add onto this, you may find the _countof() macro useful - it does the equivalent of what you've done ;)
First, a better usage to compute number of elements when the actual array declaration is in scope is:
sizeof array / sizeof array[0]
This way you don't repeat the type name, which of course could change in the declaration and make you end up with an incorrect length computation. This is a typical case of don't repeat yourself.
Second, as a minor point, please note that sizeof is not a function, so the expression above doesn't need any parenthesis around the argument to sizeof.
Third, C doesn't have references so your usage of & in a declaration won't work.
I agree that the proper C solution is to pass the length (using the size_t type) as a separate argument, and use sizeof at the place the call is being made if the argument is a "real" array.
Note that often you work with memory returned by e.g. malloc(), and in those cases you never have a "true" array to compute the size off of, so designing the function to use an element count is more flexible.
Regarding int main():
According to the Standard, argv points to a NULL-terminated array (of pointers to null-terminated strings). (5.1.2.2.1:1).
That is, argv = (char **){ argv[0], ..., argv[argc - 1], 0 };.
Hence, size calculation is performed by a function which is a trivial modification of strlen().
argc is only there to make argv length calculation O(1).
The count-until-NULL method will NOT work for generic array input. You will need to manually specify size as a second argument.
This is a old question, and the OP seems to mix C++ and C in his intends/examples. In C, when you pass a array to a function, it's decayed to pointer. So, there is no way to pass the array size except by using a second argument in your function that stores the array size:
void func(int A[])
// should be instead: void func(int * A, const size_t elemCountInA)
They are very few cases, where you don't need this, like when you're using multidimensional arrays:
void func(int A[3][whatever here]) // That's almost as if read "int* A[3]"
Using the array notation in a function signature is still useful, for the developer, as it might be an help to tell how many elements your functions expects. For example:
void vec_add(float out[3], float in0[3], float in1[3])
is easier to understand than this one (although, nothing prevent accessing the 4th element in the function in both functions):
void vec_add(float * out, float * in0, float * in1)
If you were to use C++, then you can actually capture the array size and get what you expect:
template <size_t N>
void vec_add(float (&out)[N], float (&in0)[N], float (&in1)[N])
{
for (size_t i = 0; i < N; i++)
out[i] = in0[i] + in1[i];
}
In that case, the compiler will ensure that you're not adding a 4D vector with a 2D vector (which is not possible in C without passing the dimension of each dimension as arguments of the function). There will be as many instance of the vec_add function as the number of dimensions used for your vectors.
int arsize(int st1[]) {
int i = 0;
for (i; !(st1[i] & (1 << 30)); i++);
return i;
}
This works for me :)
length of an array(type int) with sizeof:
sizeof(array)/sizeof(int)
Best example is here
thanks #define SIZE 10
void size(int arr[SIZE])
{
printf("size of array is:%d\n",sizeof(arr));
}
int main()
{
int arr[SIZE];
size(arr);
return 0;
}

How to dynamically array of pointers specifying two dimensions at run time with a single malloc() call [duplicate]

I am writing C code and I would like to heap allocate 512*256 bytes. For my own convenience I would like to be able to access the elements with the syntax array[a][b]; no arithmetic to find the right index.
Every tutorial I see online tells me to create an array of pointers that point to arrays of the rows I want in my array. This means that each subarray needs to be malloc'd and free'd individually. I am interested in a solution that only requires one call to malloc and one call to free.(Thus all elements are contiguous) I think this is possible because I will not be constructing a jagged array.
I would appreciate if anyone could share the syntax for declaring such an array.
Well, if you want to allocate array of type, you assign it into a pointer of that type.
Since 2D arrays are arrays of arrays (in your case, an array of 512 arrays of 256 chars), you should assign it into a pointer to array of 256 chars:
char (*arr)[256]=malloc(512*256);
//Now, you can, for example:
arr[500][200]=75;
(The parentheses around *arr are to make it a pointer to array, and not an array of pointers)
If you allocate the array like this, it requires two calls to free, but it allows array[a][b] style syntax and is contiguous.
char **array = malloc(512 * sizeof(char *));
array[0] = malloc(512*256);
for (int i = 1; i < 512; i++)
array[i] = array[0] + (256 * i);
See array2 here for more information: http://c-faq.com/aryptr/dynmuldimary.html
This is easy assuming you don't need compatibility with the ancient C89 standard (among current C compilers, only MSVC and a few embedded-target compilers are that backwards). Here's how you do it:
int (*array)[cols] = malloc(rows * sizeof *array);
Then array[a][b] is valid for any a in [0,rows) and b in [0,cols).
In the language of the C standard, array has variably-modified type. If you want to pass the pointer to other functions, you'll need to repeat this type in the function argument list and make sure that at least the number of columns is passed to the function (since it's needed as part of the variably-modified type).
Edit: I missed the fact that OP only cares about a fixed size, 512x256. In that case, C89 will suffice, and all you need is:
int (*array)[256] = malloc(512 * sizeof *array);
The exact same type can be used in function argument lists if you need to pass the pointer around between functions (and also as a function return type, but for this use you might want to typedef it... :-)
Since you know the size of the array ahead of time, you could create a struct type that contains a 521x256 array, and then dynamically allocate the struct.
It is possible to dynamically allocate the same kind of multidimensional array that
static char x[512][256];
gives you, but it's a wee tricky because of type decay. I only know how to do it with a typedef:
typedef char row[512];
row *x = malloc(sizeof(row) * 256);
This only lets you determine the size of the second dimension at runtime. If both dimensions can vary at runtime, you need a dope vector.
If you know the size of the array, you can typedef it, and make a pointer to it. Here is a short snippet that demonstrates this use:
#include <stdio.h>
#include <stdlib.h>
typedef int array2d[20][20];
int main() {
int i,j;
array2d *a = malloc(sizeof(array2d));
for(i=0;i!=20;i++)
for(j=0;j!=20;j++)
(*a)[i][j] = i + j;
for(i=0;i!=20;i++)
for(j=0;j!=20;j++)
printf("%d ",(*a)[i][j]);
free(a);
return 0;
}
All great answers. I just have one thing to add for old weirdos like me who enjoy "retro" coding 16 bit with old compilers like Turbo C, on old machines. Variable length arrays are wonderful, but not needed.
char (*array)[81];
int lineCount;
/* Go get your lineCount.*/
lineCount = GetFileLines("text.fil");
array = malloc(lineCount * 81);
This is how we did "VLA" back in the olden days. It works exactly the same as
char (*array)[81] = malloc(lineCount * 81); /* error pre C99 */
without the luxury of VLA.
Just my old and tarnished 2 cents.

Is it possible to pass a pointer to and array as a function parameter?

I have two integer arrays created at runtime (size depends on the program input). At some point I need to update the contents of an array with the contents of the other doing some calculations.
First I thought about passing those arrays as parameters to a function because I didn't find a way to return functions in C (don't think it's possible). After realizing that was a bad idea since parameters are not really modifiable as they're copied to the stack I resorted to change to array pointers instead.
While the function is still empty, this is the code I have:
1st take (code compiles, no errors):
// Elements is just to be able to iterate through their contents (same for both):
void do_stuff(int first[], int second[], int elements) {}
// Call to the function:
do_stuff(first, second, elements);
2nd take, attempt to translate to pointers to be able to modify the arrays in place:
void do_stuff(int *first[], int *second[], int elements) {}
// Call to the function:
do_stuff(&first, &second, elements);
This code lead to some rightful compile time errors, because apparently what I thought to be pointer to arrays were arrays of pointers.
3rd take, what I think it'd be the right syntax:
void do_stuff(int (*first)[], int (*second)[], int elements) {}
// Call to the function:
do_stuff(&first, &second, elements);
Still this code produces compile time errors when trying to access the elements of the arrays (e.g. *first[0]):
error: invalid use of array with unspecified bounds
So my question is regarding the possibility of using an array pointer as a parameter of a function, is it possible? If so, how could it be done?
Anyway, if you think of a better way to update the first array after performing calculations involving the contents of the second please comment about it.
An array decays to a pointer to the data allocated for the array. Arrays are not copied to the stack when passing to functions. Thus, you needn't pass a pointer to the array. So, the below should function fine.
// Elements is just to be able to iterate through their contents (same for both):
void do_stuff(int first[], int second[], int elements) {}
// Call to the function:
do_stuff(first, second, elements);
The cause of your errors on your second attempt are because int *first[] (and the others like it) are actually of the type array of pointer to int.
The cause of your third errors are because *first[N] is actually *(first[N]), which cannot be done with ease. Array access is really a facade over pointer arithmetic, *(first + sizeof first[0] * N); however, you have an incomplete element type here -- you need to specify the size of the array, otherwise sizeof first[0] is unknown.
Your first attempt is correct. When passing an array as a parameter in C, a pointer to the first element is actually passed, not a copy of the array. So you can write either
void do_stuff(int first[], int second[], int elements) {}
like you had, or
void do_stuff(int *first, int *second, int elements) {}
In C arrays automatically decay to pointers to data, So, you can just pass the arrays and their lengths and get the desired result.
My suggestion is something like this:
void dostuff(int *first, int firstlen, int *second, int secondlen, int elements)
Function call should be:
do_stuff(first, firstlen, second, secondlen, elements);
I am not very clear from your question, why you need elements. But, you must pass array lengths as arrays automatically decays to pointers when passed to a function, but, in the called function, there is no way to determine their size.

Is there a standard function in C that would return the length of an array?

Is there a standard function in C that would return the length of an array?
Often the technique described in other answers is encapsulated in a macro to make it easier on the eyes. Something like:
#define COUNT_OF( arr) (sizeof(arr)/sizeof(0[arr]))
Note that the macro above uses a small trick of putting the array name in the index operator ('[]') instead of the 0 - this is done in case the macro is mistakenly used in C++ code with an item that overloads operator[](). The compiler will complain instead of giving a bad result.
However, also note that if you happen to pass a pointer instead of an array, the macro will silently give a bad result - this is one of the major problems with using this technique.
I have recently started to use a more complex version that I stole from Google Chromium's codebase:
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
In this version if a pointer is mistakenly passed as the argument, the compiler will complain in some cases - specifically if the pointer's size isn't evenly divisible by the size of the object the pointer points to. In that situation a divide-by-zero will cause the compiler to error out. Actually at least one compiler I've used gives a warning instead of an error - I'm not sure what it generates for the expression that has a divide by zero in it.
That macro doesn't close the door on using it erroneously, but it comes as close as I've ever seen in straight C.
If you want an even safer solution for when you're working in C++, take a look at Compile time sizeof_array without using a macro which describes a rather complex template-based method Microsoft uses in winnt.h.
No, there is not.
For constant size arrays you can use the common trick Andrew mentioned, sizeof(array) / sizeof(array[0]) - but this works only in the scope the array was declared in.
sizeof(array) gives you the size of the whole array, while sizeof(array[0]) gives you the size of the first element.
See Michaels answer on how to wrap that in a macro.
For dynamically allocated arrays you either keep track of the size in an integral type or make it 0-terminated if possible (i.e. allocate 1 more element and set the last element to 0).
sizeof array / sizeof array[0]
The number of elements in an array x can be obtained by:
sizeof(x)/sizeof(x[0])
You need to be aware that arrays, when passed to functions, are degraded into pointers which do not carry the size information. In reality, the size information is never available to the runtime since it's calculated at compile time, but you can act as if it is available where the array is visible (i.e., where it hasn't been degraded).
When I pass arrays to a function that I need to treat as arrays, I always ensure two arguments are passed:
the length of the array; and
the pointer to the array.
So, whilst the array can be treated as an array where it's declared, it's treated as a size and pointer everywhere else.
I tend to have code like:
#define countof(x) (sizeof(x)/sizeof(x[0]))
: : :
int numbers[10];
a = fn (countof(numbers),numbers);
then fn() will have the size information available to it.
Another trick I've used in the past (a bit messier in my opinion but I'll give it here for completeness) is to have an array of a union and make the first element the length, something like:
typedef union {
int len;
float number;
} tNumber;
tNumber number[10];
: : :
number[0].len = 5;
a = fn (number);
then fn() can access the length and all the elements and you don't have to worry about the array/pointer dichotomy.
This has the added advantage of allowing the length to vary (i.e., the number of elements in use, not the number of units allocated). But I tend not to use this anymore since I consider the two-argument array version (size and data) better.
I created a macro that returns the size of an array, but yields a compiler error if used on a pointer. Do however note that it relies on gcc extensions. Because of this, it's not a portable solution.
#define COUNT(a) (__builtin_choose_expr( \
__builtin_types_compatible_p(typeof(a), typeof(&(a)[0])), \
(void)0, \
(sizeof(a)/sizeof((a)[0]))))
int main(void)
{
int arr[5];
int *p;
int x = COUNT(arr);
// int y = COUNT(p);
}
If you remove the comment, this will yield: error: void value not ignored as it ought to be
The simple answer, of course, is no. But the practical answer is "I need to know anyway," so let's discuss methods for working around this.
One way to get away with it for a while, as mentioned about a million times already, is with sizeof():
int i[] = {0, 1, 2};
...
size_t i_len = sizeof(i) / sizeof(i[0]);
This works, until we try to pass i to a function, or take a pointer to i. So what about more general solutions?
The accepted general solution is to pass the array length to a function along with the array. We see this a lot in the standard library:
void *memcpy(void *s1, void *s2, size_t n);
Will copy n bytes from s1 to s2, allowing us to use n to ensure that our buffers never overflow. This is a good strategy - it has low overhead, and it actually generates some efficient code (compare to strcpy(), which has to check for the end of the string and has no way of "knowing" how many iterations it must make, and poor confused strncpy(), which has to check both - both can be slower, and either could be sped up by using memcpy() if you happen to have already calculated the string's length for some reason).
Another approach is to encapsulate your code in a struct. The common hack is this:
typedef struct _arr {
size_t len;
int arr[0];
} arr;
If we want an array of length 5, we do this:
arr *a = malloc(sizeof(*a) + sizeof(int) * 5);
a->len = 5;
However, this is a hack that is only moderately well-defined (C99 lets you use int arr[]) and is rather labor-intensive. A "better-defined" way to do this is:
typedef struct _arr {
size_t len;
int *arr;
} arr;
But then our allocations (and deallocations) become much more complicated. The benefit of either of these approaches is, of course, that now arrays you make will carry around their lengths with them. It's slightly less memory-efficient, but it's quite safe. If you chose one of these paths, be sure to write helper functions so that you don't have to manually allocate and deallocate (and work with) these structures.
If you have an object a of array type, the number of elements in the array can be expressed as sizeof a / sizeof *a. If you allowed your array object to decay to pointer type (or had only a pointer object to begin with), then in general case there's no way to determine the number of elements in the array.

Resources