List parameters in recursive calls (C) - c

I'm designing a recursive algorithm :
int f(int[] a, int[] b){
----changing a here
----changing b here
f(a,b)
----writing a here
----writing b here
}
I know all arrays are pointers so this code should be problematic. It'll write the final values of a and b after all the recursive calls finished. I dont want that to happen.
What should I do to pass that array to recursive calls as regular "pass by value"?
PS: Arrays may be dynamically allocated or resized etc anywhere in recursive calls.

I will assume that int f(int[] a, int[] b) is a typo: it should be int f(int a[], int b[]).
First of all, arrays and pointers are different. Under many circumstances, the name of an array "decays" to a pointer to its first element, but not always. Otherwise, sizeof a, for an array a wouldn't "work".
Secondly, let's ignore recursion for a moment. Let's also make the function prototype simpler:
int g(int *a);
(I changed int a[] to int *a, because in this context, the name of an array is equivalent to a pointer.)
Now, you say that you may "dynamically allocate or resize" the array in the function call. Since everything is passed by value in C, a dynamic allocation or resizing of a inside g() cannot be seen by the caller: the caller would still have the old value of a. But more importantly, if the "original" type of a was an array, i.e., the caller had code like:
int data[SIZE];
g(data);
then trying to resize data in g() is bad, because the parameter specified in the call wasn't dynamically allocated to begin with. You can only dynamically resize something that was the result of malloc(), calloc(), or realloc().
So, there are two problems even with this simple definition:
If g() has to dynamically resize the memory referred to by the address it is given, the value has to come from a dynamic allocation, not an array,
After fixing that, since g() wants to be able to signal the change to the caller, you need to pass a pointer to what needs to be changed. So, the prototype of g() becomes: int g(int **a);.
Hopefully the above will help you get started. If you tell us more about your algorithm, in particular, what you mean by: "changing" and "writing", you will get better responses.
Edit: to answer your question in the comment:
So when I passed an array to a function it decays to a pointer and this pointer is passed by value. If that pointer is pointing a place I allocated before that call...
If you allocated something before the call, it never was an array to begin with. It can be indexed as an array, but that's not the point. So, maybe you are getting confused by the terminology here?
...when my new function changes the pointed value then that value is changed at caller, too.
The pointed-to value is changed, yes.
I dont want it to be like this, so I need a copy of the pointed value in the new function so that my original pointer's pointed value would not change. am I clear now?
It's clearer now, but then that raises more questions:
If you are going to dynamically allocate or resize the data in each call to the function, how are you going to return those new pointers? You can't. And that means you have got yourself a memory leak. Unless you free() the data in the (recursively called) function itself.
How would you resize the pointer? You may not be able to know the size of the data pointed to, unless you use a sentinel value.
Are you using the function to iteratively solve a puzzle or a problem? Are you free()ing your data in each invocation of the function? If you can tell us, exactly what are you trying to do?

All arrays are not pointers.
See these:
http://c-faq.com/aryptr/practdiff.html
http://c-faq.com/aryptr/aryptrequiv.html
http://c-faq.com/aryptr/ptrkindofary.html - specifically this one

Assuming you want the order of the output to be the same as in your original, if you don't want the outer call to see changes to your arrays made in the recursive call, you need to copy them. The easiest way is probably to allocate them on the stack then memcopy from the argument, though that will cause a SO if it gets too big. The second easiest is to malloc and free them. You will probably need to pass the array size around too. You can't pass arrays by value on the stack in C.

Just print them before passing them to the next level of recursion.

Your question isn't terribly clear but what I'm reading is this:
You have a recursive algorithm that operates on two heap-allocated arrays. It is possible that one of the recursive calls will have to reallocate the arrays, and so when it returns to the next level up, the old pointers won't be valid anymore. You want to know how to "pass the arrays by value" in order to avoid this.
First, you cannot pass an array by value in C. Period. Arrays are always passed as pointers to the first element, and there's no way around that.
Second, the answer is always another level of indirection. :)
In order to solve the problem of having to reallocate the arrays during the recursive call, what you want to do is have the function take two pointer-to-pointers (int**), where *a gives the address of the pointer to the first element of the A array, and (*a)[n] gives the nth element of the a array. That way, you can reallocate the array to your heart's content, (changing the value of *a) but the value of a itself always remains the same. By doing this, instances of the function further up the call stack will automatically inherit the reallocations made by the recursive calls because the pointed-to value (*a) of the pointer (a) that they passed to the recursive call was modified to reflect the new location of the actual data.
e.g.
int f(int** a, int** b)
{
/* Do stuff on arrays using (*a)[n] and (*b)[n] */
if (some_condition) {
/* Time to reallocate */
*a = realloc(*a, new_size);
*b = realloc(*b, new_size);
}
/* Do stuff on arrays using (*a)[n] and (*b)[n] */
f(a, b); /* Recursive call */
/* Do more stuff using (*a)[n] and (*b)[n] */
/* a and b are still valid pointers, even though *a and *b might point somewhere new */
return foo;
}
void use_f(void)
{
int* a = malloc(starting_size);
int* b = malloc(starting_size);
f(&a, &b);
}

Given the requirements:
int f(int[] a, int[] b){
----changing a here
----changing b here
f(a,b)
----writing a here
----writing b here
}
What should I do to pass that array to recursive calls as regular "pass by value"?
PS: Arrays may be dynamically allocated or resized etc anywhere in recursive calls.
The code in f() is either authorized to make changes to the arrays (as now), or it is not authorized to make changes. If it is authorized to make changes, then there is nothing much you need to do, except worry about whether you are going to leak memory if you are using dynamic allocation.
If the code is not authorized to change the arrays, then it will have to make copies of the arrays. You can prevent the code from casually modifying them by including appropriate const qualifiers:
int f(const int *a, const int *b) { ... }
Note that you cannot pass arrays by value in C. You could have the caller pass a modifiable copy - or you can have the receiver (callee?) make the copy; one or the other will have to o so if the receiver is going to make modifications when it shouldn't.

The easiest and safest option is to pass a pointer and a size. Say you are working on something like quick-sort:
void sort_range( int* ptr, size_t count )
{
size_t pivot;
assert( ptr ); /* make sure we have memory */
if ( count < 2 ) return; /* terminate recursion */
pivot = partition( count ); /* select a pivot */
assert( pivot < count ); /* make sure we don't overrun the buffer */
sort_range( ptr, pivot ); /* sort left part */
sort_range( ptr + pivot, count - pivot ); /* sort right part */
merge( ptr, count, pivot ); /* merge ranges */
}
Always be conscious about size of the memory chunk you are working with. Unfortunately C doesn't make it easy, so you have to develop a habit of checking your memory ranges.

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

Initially mallocate 0 elements to later reallocate and measure size

I have a function that will add a new position to an array by reallocating new memory every time it is called.
The problem is that, for each call I need it to add one position to the array, starting from 1 at first call, but I understand that I have to mallocate before reallocating.
So my question is, can I initially do something like p = malloc(0) and then reallocate for example using p = (int *)realloc(p,sizeof(int)) inside my function? p is declared as int *p.
Maybe with a different syntax?
Of course I could make a condition in my function that would mallocate if memory hasn't been allocated before and reallocate if it has, but I am looking for a better way.
And the second problem I have is... Once reallocated more positions, I want to know the size of the array.
I know that if, for example, I declare an array a[10], the number of elements would be defined by sizeof(a)/sizeof(a[0]), but for some reason that doesn't work with arrays declared as pointers and then reallocated.
Any advice?
You could initialize your pointer to NULL, so that the first time you call realloc(yourPointer, yourSize), it will return the same value as malloc(yourSize).
For your second problem, you could use a struct that contains your pointer and a count member.
struct MyIntVector {
int * ptr;
size_t count;
}
Then you probably will want to define wrapper functions for malloc, realloc, and free (where you could reset ptr to NULL), that takes your struct as one of the parameters, and updates the struct as needed.
If you want to optimize this for pushing 1 element at a time, you could add a allocatedCount member, and only realloc if count == allocatedCount, with a new allocatedCount equals (for example) twice the old allocatedCount.
You should implement this in a MyIntVector_Push(MyIntVector *, int ) function.
You will then have a simplified c version of c++ std::vector<int> (but without automatic deallocation when the object goes out of scope).
As ThreeStarProgrammer57 said just use realloc.
realloc(NULL, nr_of_bytes) is equivalent to malloc(nr_of_bytes)
so
p = realloc(p, your_new_size)
will work just fine the first time if p is initialized to NULL. But be sure to pass the number of bytes you need after resizing, not the additional space that you want, as you have written your question.
As regarding the size, you have to keep track of it. That's the way C was designed.

Is the gist/importance of pointers due to the fact that non-primitive data requires multiple memory blocks?

I feel like this is the final piece in me understanding pointers. "Why are pointers important?"
(I mean, I'm sure there's a lot of reasons, but is this not the biggest?)
For awhile I've understood that int num = 5; was done because num is a way for us to refer to the value stored at whatever memory address we put 5 into. If I then do num = 10; it updates that memory address to store 10 instead, and num still points to the value at that particular memory address. Am I right so far?
So I was confused why we wouldn't just do char str = "string", or the same for other objects. Is it because what we're trying to store cannot be stored in one memory block, unlike int and other primitives?
We do it because we need multiple memory blocks, and pointers effectively give us a reference to where it starts and then we can go as far as we need to collect all the data needed for the object?
Is the importance of pointers due to the fact that non-primitive data requires multiple memory blocks? We need multiple memory blocks, and pointers effectively give us a reference to where it starts and then we can go as far as we need to collect all the data needed for the object?
No. What you are describing is the important of arrays.
So what is the importance of pointers?
Suppose you have some data:
12
What can you do with that data? You can store it in a storage location and fetch it from that location later when you need it.
int height = 12;
You can pass it as a value to a method:
doit(12);
You can compare it for equality with other values:
if (height == 13)
and a few other things as well, but these are some of the big ones.
Well, the same thing is true of pointers. Pointers are values, so they can be stored, fetched, passed and compared. But any addressable storage location can be turned into a pointer. So this is the power of pointers in C: they allow you to treat storage locations like any other data.
and num still points to the value at that particular memory address
No, because num is not a pointer. I'm counting beans here, but that's important to get your ideas right. When you define a variable num, the compiler assigns the name num to a memory address, which stays valid as long as the variable is in scope - for the whole program, if it's a global variable, or until your function returns, for local variables.
Objects can be any size, for example, a structure might consist of a lot of elements. And something like
char c[100]="string"
is perfectly valid; there are no pointers involved (yet).
One of the reasons why you need pointers is when you call a function. Normally, all parameters to a function are called by value. So, if you have a function
void swap (int x, int y) {
int temp=x;
x=y;
y=temp;
}
and call it
int a=3;
int b=5;
swap(a, b);
printf("%d %d\n", a, b);
you'll get output values 3 and 5 - the variables have, obviously, not been swapped. The reason for this is the compiler creates copies of the variables and passes the copies to swap.
Now, if you want to tell the compiler "I don't want copies, i want swap to change the memory locations that i named a and b", you need pointers:
void swap (int *x, int *y) {
int temp=*x;
*x=*y;
*y=temp;
}
int a=3;
int b=5;
swap(&a, &b);
printf("%d %d\n", a, b);
The & operator tells the compiler "I want the memory address that i named a, not the value that i wrote into that memory address". Within the swap function, the * means "x is not the value that i want, it's the address of the memory i really want to change - the variable that belongs to the function that called me". Other programming languages like pascal call this "call by reference", vs. "call by value" in C.
Now your language has pointers. Let's reconsider strings, and arrays.
If i call a function
myfunction("Thisisaverylongstringthatjustwontendnoway....")
the call by value has to copy a lot of bytes from the caller to the callee, which is inefficient. So, one of the design decisions in C was:
Whenever a function calls another, passing an array as a parameter, the array is not passed by value, instead, we automatically pass a pointer the the start of the array, making it a call by reference.
So, in function calls, arrays (and strings are just a special case of an array) are always passed as pointer. Which is why, in C, you have to learn about pointers quite soon; you can get along without them much longer in, say, Pascal. Or Java (where, behind the scenes, you work with pointers all the time when you're working with Objects, but Java hides that from you).
And this is why pointers are, very often, introduced shortly after arrays and strings, when you learn C. As soon as you know what a function is, and what an array, or a string, is, you need to know about pointers or you won't get functions and arrays together.
Your last sentence about "multiple memory blocks" isn't correct in the sense that anything that's larger than a few bytes needs a pointer - structures do not - but, in most cases, your program will just be faster with pointers. If you have two strings, each 100 bytes long, and want to swap them, you'd need to do a lot of copying stuff around. Just swapping the pointers is much faster (typically, a pointer needs 4-8 bytes), so as soon as you're dealing with larger objects, you want to deal with pointers pointing to them, for efficiency reasons.
Now i haven't even begun with dynamic memory allocation .. but i guess my answer is large enough already.

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