I have an array of numbers ..
what is needed : to create 2 new arrays by malloc
one for even numbers and one for odd numbers
and we need to print them in main with the size of each array too
Array is 1,2,5,6,8,4,5,10,65,69,98,76,46,49,67
Even Array must be: 2,6,8,4,10,98,76,46
Odd Array must be: 1,5,5,65,69,49,67
The function must be written like this (this is how the teacher wants)
void evenodd(int a[],int** even,int* evensize,int** odd,int* oddsize)
my code:
#include <stdio.h>
#include <stdlib.h>
#define N 15
void evenodd(int a[],int** even,int* evensize,int** odd,int* oddsize)
{
int i,j,cnte,cnto,e,o;
cnte=cnto=0;
for(i=0;i<N;i++)
if(a[i]%2==0) cnte++;
else cnto++;
even=(int**)malloc(sizeof(int)*cnte);
*evensize=cnte;
odd=(int**)malloc(sizeof(int)*cnto);
*oddsize=cnto;
for(i=0,o=0,e=0;i<N;i++)
if(a[i]%2==0)
even[e++]=a[i];
else odd[o++]=a[i];
return;
}
int main()
{
int i;
int a[N]={1,2,5,6,8,4,5,10,65,69,98,76,46,49,67};
int *even,evensize,*odd,oddsize;
evenodd(a,&even,&evensize,&odd,&oddsize);
printf("Even Numbers Array: ");
for(i=0;i<evensize;i++)
printf("%d ",even[i]);
printf("\nSize of even array is: %d",evensize);
printf("\n\n");
printf("Even Numbers Array: ");
for(i=0;i<oddsize;i++)
printf("%d ",odd[i]);
printf("\nSize of even array is: %d",oddsize);
}
i think the error is in Malloc .. but i dont know why ..
Update allocation as
*even = malloc(sizeof(int)*cnte);
*odd = malloc(sizeof(int)*cnto);
and use as
for(i=0,o=0,e=0;i<N;i++)
if(a[i]%2==0)
(*even)[e++]=a[i];
else
(*odd)[o++]=a[i];
Your malloc calls are:
even=(int**)malloc(sizeof(int)*cnte);
...
odd=(int**)malloc(sizeof(int)*cnto);
Your first clue that this is wrong should be that even and odd are output parameters to your evenodd function, but here you're modifying local variables. C passes arguments by value; in order to modify objects passed by the caller, you must add a level indirection (a pointer). (See my answer to C Programming: malloc() inside another function for an explanation about this.)
Therefore the malloc calls should be:
*even=malloc(sizeof(int)*cnte);
...
*odd=malloc(sizeof(int)*cnto);
Note that in C, it is unnecessary to explicitly cast the result of malloc (and doing so can hide errors). It's also generally recommended to use p = malloc(sizeof *p) instead of p = malloc(sizeof (type)) so that if the type of p changes, you don't silently allocate an incorrect buffer size:
*even=malloc(sizeof **even * cnte);
...
*odd=malloc(sizeof **odd * cnto);
Since C function calls use pass by value, to pass back a value through an out parameter, you need a pointer to the variable that will hold the value being passed back. But, within that function, you need to dereference the pointer to change the value stored in the variable so that the caller sees the value being passed back. (You get this right for your counter function parameters, evensize and oddsize.)
To take an example, your even array is being assigned like this:
even=(int**)malloc(sizeof(int)*cnte);
When you dynamically allocate an item (or in this case an array of items) of type FOO, malloc() logically returns a FOO *. You should not cast the return value of malloc(), but your cast is wrong anyway, it should have been:
even=(int*)malloc(sizeof(int)*cnte);
However, even is an int **, which is a pointer to the int *even variable in main(). To let main() see the result, you have to dereference the pointer passed to your function. As mentioned previously, you should not cast the result of malloc(), as it can mask an error if its prototype is missing, which can lead to undefined behavior in the worst case.
*even=malloc(sizeof(int)*cnte);
In C, the declaration of the variable mimics use. So int **even means that **even is an int. So, to assign an int value properly, even has to be dereferenced twice. The first time to get to the array allocated by malloc(), and a second time to reach the desired index position. So, your assignment statement:
even[e++]=a[i];
is wrong because it is assigning an int value to an int * type since even is only dereferenced once. Since even is a pointer to an int *, use:
(*even)[e++] = a[i];
Similarly, make the same corrections for the odd function parameter.
Related
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;
}
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;
}
I am new to LeetCode and am trying to improve upon my problem solving techniques. I am attempting to solve the Two Sum Problem in C and have run into trouble with the final return statement. The code initially provided to me by LeetCode was a function called "int* twoSum" and the goal is to find the two indices in an array that produce the target number. The function lists a couple parameters that I assumed were provided in main since it was not shown.
I changed the name of the function to just "int twosum" and removed the int* returnSize because I am not a big fan of unnecessary pass by address instead of by value and felt it wouldn't have a significant impact. However, after trying to run my code I run into the warning error: "returning 'int *' from a function with return type 'int' makes integer from pointer without a cast"
Could someone who understands this issue or has solved the problem before on LeetCode please provide insight as to what I need to correct? Thank you.
int twoSum(int *nums, int numsSize, int target){
int outerCount; //loop control variable for outer loop
int innerCount; //loop control variable for inner loop
int array[2]; //array that stores indices of numbers that produce target
for(outerCount = 0; outerCount < numsSize; outerCount++)
for(innerCount = outerCount + 1; innerCount < numsSize; innerCount++)
{
if(nums[outerCount] + nums[innerCount] == target)
{
array[0] = outerCount;
array[1] = innerCount;
}
}
return array;
}
The problem asks you to return two integers (indices), so a return type of int is pretty clearly incorrect. int is a single integer; two return two integers you need to return an array of int, or struct containing two integer members. C doesn't allow you to return arrays by value, so if you need to return an array, you need to return an int*. That's just the way C is.
Note that since you cannot return an array by value, you also cannot return a pointer to an automatically allocated array, since that object's lifetime will end when the function returns. So you need to dynamically allocate the array (unless it is passed to your function as an argument, which is a very common style). In this case, it is pretty clear that a dynamically allocated return value is desired, based on the comment:
/* Note: The returned array must be malloced, assume caller calls free(). */
Whether or not you like this style, you will need to conform to it for this exercise, since it is pretty clear that the caller will call free()on the returned pointer, and calling free() on a pointer not originally returned by malloc is Undefined Behaviour (and very likely to crash your program). (You can free(NULL), but that's also a violation of the calling contract, which will segfault when the caller tries to examine the non-existent return values.)
C does let you return structs by value, but if you are going to return a struct, you and the caller need to agree on its declaration (the names of its members, for example).
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;
}
I'm new to C for numerical analysis after many years of working with Matlab. I have a function that constructs an array and I need to get it back to main(). I had the usual trouble with arrays vs. pointers, and by fiddling figured out how to do this. But the fiddling left me with a conceptual question based on the following code.
#include <stdio.h>
void array_set(int y_out[2][2]);
void int_set_wrong(int y);
void int_set_right(int *y);
int main (int argc, const char * argv[]) {
int y_array[2][2]={{0,0},{0,0}};
int y_int_1 = 0;
int y_int_2 = 0;
array_set(y_array);
int_set_wrong( y_int_1 );
int_set_right( &y_int_2 );
printf("\nValue array: %d \n",y_array[0][0]);
printf("Value int wrong: %d \n",y_int_1);
printf("Value int right: %d \n",y_int_2);
return 0;
}
void array_set(int y_out[2][2]){
y_out[0][0] = 10;
y_out[1][0] = 20;
y_out[0][1] = 1;
y_out[1][1] = 2;
}
void int_set_wrong(int y){
y = 10;
}
void int_set_right(int * y){
*y = 10;
}
The snippet above returns:
Value array: 10
Value int wrong: 0
Value int right: 10
My question is in a few parts,
first, why does the function 'array_set' work? I would expect it to fail in the same way that 'int_set_wrong' did.
How are ints and int arrays treated differently in passing?
Furthermore, in the case of 'int_set_wrong', is there a local version of y?
If so, why is there not a local version of y_out in case of setting the array?
Thanks for the help. As an aside, if there is anything that will cause problems with my implementation of array_set, please chime in.
--Andrew
In int_set_right() you passed the address of the variable y_int_2 (which you declared and defined in main()) through the operator &.
int_set_right( &y_int_2 );
Since the function had access to the actual variable y_int_2 through the pointer y (set to the value of the address of y_int_2 from &y_int_2), you assigned y_int_2 the value 10 when you assigned *y = 10.
You can read *y = 10 as:
the value of the variable whose
address is stored in y is now set to
10
But for y_int_1, you merely passed the value. So a temporary variable was created when you called int_set_wrong() which was initialized with the value of y_int_1. So all you did was change the value of the temporary of the local variable (local to int_set_wrong()).
This is why the y_int_1 declared in main() is not affected by int_set_wrong().
array_set works because you passed the address of y_array to the function through the y_out variable (which is a pointer like y in int_set_right).
Arrays are passed using pointers rather than the entire array being copied by value on the stack. Your two dimensional array makes explaining this tricky, but consider a one dimensional version:
void f(int x[]){
x[0] = 1;
x[1] = 2;
}
You could equivalently write this as:
void f(int *x){
x[0] = 1;
x[1] = 2;
}
These two declarations are identical, but I'm sure you can see that modifications made in the the second version are propagated back to the caller.
The function array_set works because when you pass an array into a function, you are really passing a pointer. Then, inside the function, you are de-referencing the array using "y_out[0][0] = 10" etc. When you use array notation, it automatically de-references the array pointer so you are able to set the values within the array.
Ints are completely different from int arrays. An array can be treated in almost every case as a pointer, in this case a pointer to int. An int is an actual numerical value. Therefore, when you pass an int into you're int_set_wrong function, it is copied (that's just what C/C++ does), and you are setting a local variable y, not the int you passed in.
You're third question is answered in the first paragraph as well. Hope this clears things up.
Your function works because in C the inner most [] in function arguments (and only there!) is equivalent to a pointer argument. Your declaration is equivalent to
void array_set(int (*y_out)[2]){
..
}
That is y_out is a pointer to int[2].
You've created 3 functions.
array_set(y_array);
Prior to this you have created an array of numbers with the line.
int y_array[2][2]={{0,0},{0,0}};
In C when you declare an array you created a pointer in your code with the name y_array the array is stored somewhere in the memory and the pointer is pointing is holding the position of the location.
So essentially its a normal pointer with a big amount of memory allocated after it.
When you pass the array to save memory and time C by default passes the pointer.
void int_set_wrong(int y);
When you pass an int it copies the value to a local variable as a result, you don't hold any address to that variable outside that function.
When you pass the reference of an int you supply the function with the address of your int variable. As a result, the function can make changes there.
As the first and third call is sharing the location of the main variable you can see the change from the main. For the second one there is no sharing of address. So the function creates its own variable which cannot be accessed from outside.