sizeof array clarification - c

I am studying for a final tomorrow in C, and have a question regarding the sizeof operator.
Let's say the size of an int is 32 bits and a pointer is 64 bits.
If there were a function:
int
foo (int zap[])
{
int a = sizeof(zap);
return a;
}
Because zap is a pointer, foo would return 8, as that's how many bytes are needed to store this particular pointer. However, with the following code:
int zip[] = { 0, 1, 2, 3, 4, 5 };
int i = sizeof(zip);
i would be 6 * sizeof(int) = 6 * 4 = 24
Why is it that sizeof(zip) returns the number of elements times the size of each element, whereas sizeof(zap) returns the size of a pointer? Is it that the size of zap is unspecified, and zip is not? The compiler knows that zip is 6 elements, but doesn't have a clue as to how large zap may be.

This is sort of an asymmetry in the C syntax. In C it's not possible to pass an array to a function, so when you use the array syntax in a function declaration for one of the parameters the compiler instead reads it as a pointer.
In C in most cases when you use an array in an expression the array is implicitly converted to a pointer to its first element and that is exactly what happens for example when you call a function. In the following code:
int bar[] = {1,2,3,4};
foo(bar);
the array is converted to a pointer to the first element and that is what the function receives.
This rule of implict conversion is not however always applied. As you discovered for example the sizeof operator works on the array, and even & (address-of) operator works on the original array (i.e. sizeof(*&bar) == 4*sizeof(int)).
A function in C cannot recevive an array as parameter, it can only receive a pointer to the first element, or a pointer to an array... or you must wrap the array in a structure.
Even if you put a number between the brackets in the function declaration...
void foo(int x[4])
{
...
}
that number is completely ignored by the compiler... that declaration for the compiler is totally equivalent to
void foo(int *x)
{
...
}
and for example even calling it passing an array with a different size will not trigger any error...
int tooshort[] = {1,2,3};
foo(tooshort); /* Legal, even if probably wrong */
(actually a compiler MAY give a warning, but the code is perfectly legal C and must be accepted if the compiler follows the standard)
If you think that this rule about arrays when in function arguments is strange then I agree, but this is how the C language is defined.

Because zip is an array and the compiler knows its size at compile-time. It just a case of using the same notation for two different things, something quite usual in C.
int
foo (int zap[])
is completely equivalent to
int
foo (int *zap)
The compiler doesn't have any idea how big zap could be (so it leaves the task of finding out to the programmer).

zip is a memory block of 6 * sizeof(int) so it has a size of 24 (on your architecture).
zap (it could be also written as int *zap in your function declaration) however can point to any memory address and the compiler has no way of knowing how much space starting at this (or even containing this) address has been allocated.

The size of zip is known at compile time and the size of zap is not. That is why you are getting the size of a pointer on sizeof(zap) and the size of the array on sizeof(zip).

There are some situations wherearrays decay to pointers. Function calls is one of those.

because it has been statically initialized with 6 elemens.

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 does the computer(C compiler, or something else) handle "automatic array declaration"? | C language

I am attempting to return a dynamically declared array from a function; thus far I am returning a structure to hold a pointer to the memory block that malloc() assigned for the array AND an integer to store the length of the array.
This made me wonder; How does the C Compiler(or whatever) handle an automatic array declared in a program?
eg.
main()
{
//delcare an array holding 3 elements
int array[] = {1,2,3};
/*variable to hold length of array
*size of array / size of 1st element in the array == length of the array
*this will == 3
*/
int array_Length = (sizeof(array))/(sizeof(*array));
//call malloc for a block of memory to hold 3 integers(worth of memory)
int* ptr = malloc(3*(sizeof(int)));
/*not exactly sure what this formula means when using a pointer???
*but it seems to always == 1
*/
int dynamic_array_length = (sizeof(ptr))/(sizeof(*ptr));
return 0;
}
My point is, the sizeof() operator somehow knows that the automatically declared array has 3 integers within it.
Or more generally:
sizeof(array)
where array is (N x type_size)
N is the number of elements within the array
type_size is the number of bytes of memory used to store the data type
Are automatic arrays stored with additional information about their size/length?
Are dynamic arrays stored differently? (I know that we control when a dynamic variable is freed from memory)
Operator sizeof is a compile-time construct (with the exception of VLA arguments). It tells you the object size in bytes because it knows the exact compile-time object type. And when you know the exact type the size is also immediately known. There's no need to separately store the number of elements anywhere.
Your declaration
int array[] = {1,2,3};
is equivalent to
int array[3] = {1,2,3};
meaning that array has type int[3]. So your sizeof(array) is interpreted as sizeof(int[3]), which is immediately known to the compiler.
sizeof does not know and does not care about any "dynamic arrays" of yours. All it cares about is that in sizeof(ptr) operator sizeof is applied to a pointer. So it evaluates to pointer size.
sizeof(...) is not a function call. It doesn't actually execute at runtime - that value is replaced at the compile time, so what's actually compiled is:
int array_length = 3;
The calculation of dynamic_array_length is incorrect. You divide the size of a pointer by the size of int. Which in your case happens to be the same and get 1 as a result.
Your dynamic array is stored differently - the pointer (on the stack) is separate from the data (on the heap). The first array is just data on the stack - the memory address is constant (for that stack frame) and gets used where needed.
Disregarding VLAs, the array size of an automatic array is a fact completely known at compile time, and is actually a part of the type of the variable. sizeof is a query (resolved at compile time) to the type system, which is a thing that exists only in the compiler internal data structures while it is compiling. The result is the actual variable size, which is treated essentially as if it was directly written in the source code.
Things about sizeof has been discussed enough, and we know it is a compile-time action.
But in fact, It is true that there is something about size is stored and used in run-time for dynamic variables. Otherwise the free can not do its work correctly.
Here is a good reference: how-do-malloc-and-free-work
You are hitting one of the inconsistencies of C. An array is just a pointer, except where it has been declared. The result of sizeof (somearray) is different, depending upon whether or not sizeof is used in the function defining somearray. In, C, as soon as you move away from the definition, there is no knowledge of anything other than the type of object in the array. That is just one of the many reasons why C programming is so error prone.
Most programming languages other than C or those derived from C, maintain an array descriptor that includes the number of dimensions, the number of elements, and, in some cases, the array bounds.
In the case of dynamic arrays, the library adds overhead, usually before, to the memory returned (sometimes additional overhead is added at the end). This is used so that library can know how much memory is freed.

Syntax Error : '{'

I am writing a C program that uses an array of integers which is a part of a structure. The structure is:
struct test
{
int *ques;
int a;
int b;
int len; // len is the length of the array defined in the structure as ques.
};
In a function after this declaration I have assigned a value to the len as:
cases[0].len=5; // here cases is an array of the type struct test.
and then I have used malloc to allocate memory to the array member ques as follows:
cases[0].ques=(int *)malloc(cases[counter].len*sizeof(int));
After that I have tried to fill in the array ques as follows:
cases[0].ques[5]={-7,-6,-5,-4,-3};
and while compiling I get an error at the above line stating that:
maxmin.c(47) : error C2059: syntax error : '{'
Can you please help me out?
This is invalid: cases[0].ques[5]={-7,-6,-5,-4,-3};
You can initialize an array in C this way, only at the time of declaration of array.
To fill in the values at this point in your C program you should use for loop to fill every index separately.
Right now the C compiler parses this statement as:
Value of index 5 of array ques at index 0 of structure array cases of type struct test is {-7,-6,-5,-4,-3}, which is certainly invalid since you cannot use { while assigning a value to a variable.
Update at OP's comment:
You can keep all the values in temp array say int temp[50] = {...}; then after allocating space to ques you can use memcpy function to copy len number of values to ques.
If you have C99 or C11, you can use a compound literal in conjunction with memcpy() or memmove() to initialize the new array:
memmove(&cases[0].ques, (int []){-7,-6,-5,-4,-3}, 5 * sizeof(int));
This also fixes the problem that you allocate cases[0].ques as a pointer to 5 integers, but you then try to assign to a single element that is beyond the end of the allocated array. The code is also inconsistent in that most of it references cases[0] but the malloc() call references cases[count] in the argument list. Not automatically wrong, but definitely unusual.
The array literal can be as big as you need. The only tricky bit is the size argument (third argument) to memmove(). I ducked fast on that; repeating the compound literal doesn't feel like the right move, but manually counting isn't a good solution either.
Well, you could if memmove() wasn't a macro that objected to being given 7 arguments instead of 3 (GCC 4.8.2 on Mac OS X 10.9.2)!
(memmove)(&cases[0].ques, (int []){-7,-6,-5,-4,-3}, 5 * sizeof(int));
memmove(&cases[0].ques, ((int []){-7,-6,-5,-4,-3}), 5 * sizeof(int));
The first invokes the function memmove(), not a macro. The second creates a single argument by wrapping parentheses around the compound literal. Both compile.
Note that although the compound literal looks like a cast and a brace-initializer, I'm not sure it is strictly a cast — it is best not to think of it as a cast but as a compound literal.
Incidentally, if the objective is to add N random values to an array of N integers (as mentioned in a comment to one of the other answers), then you won't want to use this technique — the integers in the example are implausible as a random sequence. If you do want 50 random numbers in some range, you'll use a random number generator (possibly rand(), possibly
lrand48(), possibly something else) to create the values in an appropriate range, using a simple for loop to initialize the correct number of array elements.
assign value to each array element as,
cases[0].ques[0]=-7
cases[0].ques[1]=-6
...
cases[0].ques[5]=-3
since you are assigning the value after declaration. C allows {} use for initializing array at the time of declaration. not after that.
I hope you realize why cases[0].ques[5] is wrong.
int arr[5] = {1,2,3,4,5};
The above code works because you are doing the initialization of array at the declaration time.
If you have
int arr[5];
arr[5] = {1,2,3,4,5}; // THIS WONT WORK
Here, you'll have to use for loop and fill each index.
also, when you do
int arr[5];
arr[5] = {1,2,3,4,5};
In the above code, what you are trying to do is, put some value in arr[5]. That is just one index of the entire array.
Additionally, as the comment suggests, arr[5] is the 6th element in the array of size 5. Now although it won't give error, but be prepared to get some unexpected results. :)
ques[5] is an int, you cannot assign an array to it
Also, C doesn't allow to assignment to multiple elements in an array like that. You can only do it at initialization. So create a new array and initialize with those 5 elements and copy it to your destination with memcpy() or memmove()
int[] tmp = {-7,-6,-5,-4,-3};
memcpy(cases[0].ques, tmp, 5*sizeof(int));
Alternatively you can assign values to ques[i] separately
Lot of time I do not program in C, but I think the only situation in which you can do a complete array declaration is in the time that you declare it:
int a[] = {...}
But not this way:
int a[5];
a = {...};
Also, in your case, you are doing
int a[5] = {...}
and this means that you are trying to assign an array to an integer.
Also, it's better if you do not do a cast in the malloc call:
cases[0].ques = malloc(cases[counter].len * sizeof(int));
cases[0].ques[5]={-7,-6,-5,-4,-3};
You cannot do this, this initializer only valid when you define an array.
You should do something like:
for (start = -7, i = 0; i < cases[0].len; i++, start++) {
cases[0].ques[i] = start;
}

Length of array in function argument

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;
}

Resources