The following code is trying to make a point (probably the difference between arrays and local variables) I only have a vague idea on the code. Would someone please elaborate? Thanks
void doit(int x[10], int y) {
y = 30;
x[0] = 50;
}
void main(void) {
int x[10];
int y = 3;
x[0] = 5;
printf("x[0] is %d and y is %d\n", x[0], y);
doit(x, y);
printf("x[0] is %d and y is %d\n", x[0], y);
}
It is showing that arrays are not really passed directly to functions - instead, the address of the first member of the array is passed.
That means that if the called function modifies the array that was "passed", it is modifying the original array in the caller.
On the other hand, when the called function modifies the plain int parameter y, it is modifying a local copy of the variable, and the change is not reflected in the caller.
In C, all arguments are passed by value. However, arrays decay into a pointer to the first element to the array when they get passed; the result is effectively as if the array was passed by reference.
In your code, the doit() function can mutate the array pointed to by x, but it cannot mutate the simple int value in y.
y is passed by value meaning that a temporary copy is created, you have to pass it as a pointer to modify it:
void doit(int x[10], int* y) {
*y = 30;
x[0] = 50;
}
Declaring an array is also not really needed. The compiler anyway understands only that it is a pointer and does (usually) not check the boundaries.
void doit(int* x, int* y) {
*y = 30;
x[0] = 50;
}
Local variables are passed as value where as in arrays the reference is passed not the actual values. so when you change the value in child array the parent array will get changed. Arrays are same as pointers in using the reference
Related
Before I start I want to tell you I am learning to program.
What is the difference between Passing the variable to function and passing an array to the function in C?
When we pass a variable to function we are just passing the value of function. But when we pass an array we are passing somehow a pointer because when we do some changes on an array inside a function, actual array gets changed.
In order to make my question clear I am attaching code which will explain what I am asking-
Code 1:
//Passing variable to function
#include<stdio.h>
void swap(int x, int y);
int main(void)
{
//Nothing is happening to real values of variables
int x, y;
x = 1;
y = 2;
swap(x, y);
printf("%d = x \n %d = y", x, y);
}
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
Code 2:
//Here you can see the values of arrays are swapped.
#include<stdio.h>
void swap(int arr[]);
int main(void)
{
int idx, array[2];
for(idx = 0; idx < 2; idx++ )
{
scanf("%d", &array[idx]);
}
swap(array);
for(idx = 0; idx < 2; idx++, printf("\n"))
{
printf("%d", array[idx]);
}
}
void swap(int arr[])
{
int temp;
temp = arr[0];
arr[0] = arr[1];
arr[1] = temp;
}
Maybe my question is still unclear but I just want to know why the values of the array gets changed in main function as when we call the function we are just passing a function value of that variable.
In the both cases when a variable as you are saying is passed to a function or an array is passed to a function there is passed a value.
But in the first case there is passed the value of the variable while in the second case there is passed the value of the pointer to first element of an array.
Arrays used in expressions with rare exceptions are converted to pointers to their first elements.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
So having a pointer to an object you can change the pointed object.
Let's assume that you have two functions.
void f( int x )
{
x = 10;
}
and
void g( int *px )
{
*px = 10;
}
and their calls
int n = 0;
f( n );
g( &n );
You can imagine the function definitions and their calls the following way
int n = 0;
f( n );
g( &n );
//...
void f( /* int x */ )
{
int x = n;
x = 10;
}
void g( /* int *px */ )
{
int *px = &n;
*px = 10;
}
That is the both functions deal with copies of values of the expressions used as function arguments. But in case of the function g as the function gets the value of the address of the pointed object n you can change the pointed object n using the pointer (address).
In the terms of C passing an object to a function indirectly through a pointer to the object is called passing by reference.
From the C Standard
— A pointer type may be derived from a function type or an object
type, called the referenced type. A pointer type describes an object
whose value provides a reference to an entity of the referenced
type. A pointer type derived from the referenced type T is sometimes
called ‘‘pointer to T’’. The construction of a pointer type from a
referenced type is called ‘‘pointer type derivation’’. A pointer type
is a complete object type.
Pay attention to that a function declaration like this
void f( int a[], size_t n );
is equivalent to the following declaration
void f( int *a, size_t n );
And the both declare the same one function.
If you have an array as for example
#define N 10
//...
int a[N];
then it is passed to the function like
f( a, N );
then as it is followed form the first quote from the C Standard the array designator is converted to pointer to its first element. And having this pointer in the function you can change any element of the array because each element of the array in fact is passed by reference. Using the pointer arithmetic you can change any element of the pointed array. For example
void f( int *a, size_t n )
{
for ( int i = 0; i < n; i++ )
{
a[i] = i;
// that is the same as
// *( a + i ) = i;
}
}
When you pass an array, you are actually passing the base address of the same, which is a pointer to the first array element in the memory. It is inherently a call by reference, so you don't need to explicitly use a reference or & while passing into your swap function. arr decays to &(arr[0]).
On the other hand, variables are not by default passed by value, and you need to explicitly use a & to pass them by reference to get their values swapped in their memory locations and not just specific to the scope of the swap function.
What is the difference between Passing the variable to function and passing an array to the function in C?
You cannot pass an array as it is to a function. The C syntax does not allow that. When you provide the identifier of an array as argument it decays to a pointer to the first element of the array - so you pass the array by reference to its first element.
If the relative parameter of the function is of the matching pointer type, here int * or int a[], this is permissible.
Instead when providing a variable as argument you pass it by value. Means you do not access the variable provided as argument in the function itself. Rather the value is copied into a local variable of the function.
If you want to change the value of the variable passed itself, you need to use the & ampersand operator to gather the address of the variable itself. This is only permissible if the relative parameter is of matching pointer type as above.
Thus, In the first example you do not swap the values of x and y in main(). You only change x and y inside of swap() which is pretty useless.
If you want to swap xand y in main you need to define swap() as:
void swap(int* x, int* y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
and call swap() like:
swap(&x, &y);
I suggest you to learn more about pointers.
You are not passing the array as copy. It is only a pointer pointing to the address where the first element is in memory.
When passing an array as a parameter, this
void arraytest(int a[])
means exactly the same as
void arraytest(int *a)
so you are modifying the values in main. However in C function arguments are always passed by value. In case of an array (variable), while passed as a function argument, it decays to the pointer to the first element of the array. The pointer is then passed-by-value, as usual.
An array is a special variable. When you pass a regular variable to a function as an argument, its value is copied to a local variable pertaining to the function.
When you pass an array to a function as an argument, the address of the first element of the array is copied to a local variable pertaining to the function.
That is basically the difference between passing a regular variable and passing an array to a function.
There is one issue with your perception though. If you want to modify a regular variable to be passed to a function, then you need to pass its address to the function, thus the function should take a pointer type. So just use the pointer notation, i.e int *p as opposed to int p[], even though, they are equivalent as function parameters.
Your code should look like this:
#include<stdio.h>
void swap(int *x, int *y);
int main(void)
{
int x, y;
x = 1;
y = 2;
swap(&x, &y);
printf("%d = x \n %d = y", x, y);
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
I'm creating a function which modifies a variable so it can be used by the function referencing it (parent function?).
Is there a difference between using '&x' compared to using 'z' in the code below?
void changeX(int *p);
int main(void) {
int x = 10;
printf("%d\n",x);
int *z = &x;
changeX(z);
printf("%d\n",x);
// or
changeX(&x);
printf("%d\n",x);
return 0;
}
void changeX(int *p){
*p = *p + *p;
}
wildplasser made a good point, updated to show where I have gotten each value in the output.
Output is:
10
20
40
Both produce the same outcome (change x in the same way), but is there a non-obvious difference between them?
Thanks for the answers in the comments. It makes sense to me now.
The first call initializes the parameter from the argument z, i.e., the value of the argument is the value of the pointer z, which was initialized to be &x, a pointer value that points to the object x. The second call initializes the parameter from the argument &x, which is a pointer value that points to the object x. There is no functional difference between the two calls. In both cases, the parameter p in the function will have the exact same value, a pointer value that points to x, the only difference is where that value came from at the point where function was called…
Here is an example of what I mean. This example is without using pointers and the variables do not swap.
void swap(int x, int y);
main()
{
int a = 33, b = 55;
swap (a, b);
printf("a = %d, b = %d\n", a, b);
}
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
Now if you use pointers the variables a and b swap. Why is it that it only works with pointers?
C is a pass-by-value language. Always. That means with this:
void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
you're swapping the values of x and y, obtained from the values passed to the function. When you invoke like this:
int main()
{
int a = 33, b = 55;
swap (a, b); // passing values of a and b
printf("a = %d, b = %d\n", a, b);
}
the values of a and b are passed. So this is your problem. The solution is to make the values passed something that can be used to modify the caller's variables. If you want to modify those variables they need to somehow be addressable from the called code. Hmmm...
The mechanism is called "pass by address", and though it sounds fancy in reality it isn't. It is simply a retooling of pass-by-value, but with a different value type. Whereas before we were passing values of type int we will instead pass addresses of the integer variables and declare the formal parameters to be pointers to int instead. Make no mistake. They're still values, but not of the basic int type. Rather the values passed are addresses of int variables. To access the data at those addresses pointers are used in conjunction with the dereference operator (of which there are several kinds, only one shown here):
void swap(int *ptrToX, int *ptrToY)
{
int temp = *ptrToX; // dereference right, store value in temp
*ptrToX = *ptrToY; // dereference both, assigning value from right to left.
*ptrToY = temp; // dereference left, assign temp value
}
and invoked like this:
int main()
{
int a = 33, b = 55;
swap (&a, &b); // passing addresses of a and b
printf("a = %d, b = %d\n", a, b);
}
Note: Often ill-quoted as the exception to pass-by-value is passing an array. Though the phrase "decays to a pointer" is thrown about like confetti on New Years Eve, I abhor that vernacular. The verb itself implies a functional operation where there is, in fact, none.
The language specifies the value of an array used in an expression is the address of its first element. In other words, its "value" is already an address and as such can simply be passed by-value to a function expecting a pointer to the same base type. Because it is an address, the receiving parameter (a pointer, because thats what holds address values) can then be used to modify the array content from the caller. Second only to multiple levels of indirection (pointers to pointers, etc) it is easily the hardest thing for people new to C to wrap their head around, yet it is important you do so.
When you call swap, the value of the variables a and b are passed to it. These values are passed by copy. When you swap those values in swap, you are only swapping local copies of a and b.
When you pass pointers to variables to a function, you are able to modify the values of the variables in the calling function.
That's called pass by value.
You are just passing values of a & b to the swap function. The swap function copies that value into its variables x & y which are different from a & b. Hence in swap you are working on x & y instead of a & b.
On the other hand, when you pass pointers, you are passing the address where a & b are stored. Your x & y point to the same address and hence you are manipulating the content at that address where a & b are stored. Hence, main gets to see the updated values.
This is the best example to define the advantage/use of function call by reference V/s call by value
In the main() function the two variables has the value
int a = 33, b = 55;
so using these variables in the swap(a,b) function, it just passes the values to the function definition where
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
they declare again two variables x,y and the values in this variables are swapped. But the variables x and y are only known to function swap() after execution of the swap() function that variables are no longer valid. So nothing happens to the variables a,b in the main function.
So in order to swap variables using function you've to use
swap(&a,&b);
in main() function , and modify function swap()
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
Which passes the address of variables a and b , and the pointers are used to swap the variables,It gets swapped effectively. Since pointer points to the address of the variables the value of the variables get changed.
For more google "call by referece and call by value in c"
This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 9 years ago.
I dont understand what this means. If I were to try and guess I'd say byValue argument passing is when you pass an argument based on the value of an variable, so I'm thinking:
if (a == 1){
PassAnArgumentOrSomething()
}
However that is probably wrong :/
As for byReference, I have no idea.
If anyone can help me out that be awesome of you :)
With the exception of arrays and functions (see below), C always passes arguments `by value': a copy of the value of each argument is passed to the function; the function cannot modify the actual argument passed to it:
void foo(int j) {
j = 0; /* modifies the copy of the argument received by the function */
}
int main(void) {
int k=10;
foo(k);
/* k still equals 10 */
}
If you do want a function to modify its argument you can obtain the desired effect using pointer arguments instead:
void foo(int *j) {
*j = 0;
}
int main(void) {
int k=10;
foo(&k);
/* k now equals 0 */
}
This is sometimes known as `pass by reference' in other languages.
There is no pass by reference in c language
Passing by value: means that you are creating a temporary copy of the variable and sending to the parameter.
Passing by reference(no such concept in c language): means that you are just giving another name to the original variable while calling and no temporary copy of the variable is being created.
Calling by value:
int foo(int temp)
{
/.../
}
int main()
{
int x;
foo(x); /* here a temporary copy of the 'x' is created and sent to the foo function.*/
}
Calling by reference(no such concept in c language)
int foo(int& temp)
{
/.../
}
int main()
{
int x;
foo(x); /* here no temporary copy of 'x' is being created rather the variable *temp* in the calling function is just another name of the variable a in the main function*/
}
Passing an argument by value means you are passing a copy:
void f(int x)
{
x = 7;
// x is 7 here, but we only changed our local copy
}
void g()
{
int y = 3;
f(y);
// y is still 3 here!
}
Passing an argument by reference means you are not passing a copy, but instead passing some way of referencing the original variable. In C, all arguments are pass by value, but what is typically done to get the same effect as passing by reference is to pass a pointer:
void f(int *x_ptr) { *x_ptr = 7; }
void g()
{
int y = 3;
f(&y);
// y is 7 here
}
Arrays are passed in such a way that it appears similar to pass-by-reference, however what is actually happening is more complicated. For example:
void f(int a[]) { a[0] = 7; }
void g()
{
int b[3] = {1,2,3};
f(b);
// b[0] is 7 here! looks like it was passed by reference.
}
What is actually happening here is that the array b is implicitly converted to a pointer to the first element (this is known as decay). The int a[] notation for the parameter to f is actually syntactic sugar for a pointer. The above code is equivalent to:
void f(int *a) { a[0] = 7; }
void g()
{
int b[3] = {1,2,3};
f(&b[0]);
// b[0] is 7 here
}
Passing by value is passing the value itself; it makes a copy of the value, and any changes you make in the new function are NOT saved to the original variable:
void foo(int num)
{
num = 5; // Does not save to the original variable that was passed when foo was called
...
}
Passing by reference is passing the location of the variable; it allows the new function to directly edit the original variable:
void bar(int * num)
{
*num = 5; // Changes the variable in the original function
...
}
in-depth explanation
whenever a program loads, it gets a memory area so called address space which gets divided into various regions
code/text : contains the statements of program (collections of statements).
global : contains the global variable if any.
constant : used for constant or literal storage.
heap : used for dynamic memory need.
stack : function used its for variable.
consider a function so defined as
void doSomething(int x)
{
x++;
}//end of function
is called as doSomething(5) or doSomething(y) in another function or main function .
here
x is local variable to function "doSomething". It gets its home (memory location) somewhere in stack region.
When doSomething(5) is called 5 gets copied to x's memory or doSomething(y) is called value/content of y (different memory location) gets copied to x's memory. Whatever operations applied on x, will not affect y 's content/value at all. Since its memory location is different.
Whenever execution flow reachs at end of function x dies/gets destroyed. Whatever value of x is not accessible/available. In short, update is lost and y is unaffected (Change is not reflected).
This is what so called Call by Value
Now
Consider an another function so defined as
void doSomething(int *x)
{
(*x)++;
}
is called as doSomething(&y)
here x is called pointer (conceptually called reference*).It will also gets home somewhere in stack region
When doSomething(&y) is called address of y gets copied to x's location block. Since this x is special variable so called pointer that holds address and it is said that x refers/points to y.
When (*x)++ is applied, here * is indirection operator which will bring whom x refer to the context ie. (*x)++ will indirectly change the value of y by 1. Nothing will happen to x's value itself.
Whenever execution flow reach at end of function *x dies/gets destroyed as expected but this time change is made to y (indirectly) which is still alive somewhere in stack region (change is reflected).
Also not that this time doSomething(&5) or doSomething(any literal) is not possible because it's illegal to get address of any literal.
This is what so called Call by Reference/Call by Pointer.
note that Call by Reference has another meaning in C++ but conceptually remains same.
Let's look at the "calling" of functions first.
In C, the arguments to a function are typically "by value". Below, after calling sqrt(x), the value x is not changed for sqrt() received a copy of the value x, thus never gaining an ability to affect x.
y = sqrt(x);
// x did not change
printf("%f is the square root of %f\n", y, x);
Array parameters to a function appear to be "by reference". After fgets() is called, buf is expected to be altered. fgets() did not receive a copy of, but a "reference" to the char array. Thus fgets() could affect the contents of the array.
char buf[80] = { 0 }; // array 80 of char
printf("Before <%s>\n", buf); // "<>"
fgets(buf, sizeof buf, stdin);
printf("After <%s>\n", buf); // "<Hello World!>"
Let's now look at the "receiving" part: the function.
Function parameters of type double, int, struct types are received by value. The value of f here is the copy of the x above. Any changes made to f do not affect the x in the calling code.
double sqrt(double f) {
double y;
... // lots of code
return y;
}
Now comes the tricky bit and this is where there is lots of discussion in C.
The parameter s in fgets() below was not assigned the buf above (array 80 of char), instead s was assigned the pointer type derived from buf: address of the first element of an buf. By knowing the address of the array elements of buf (via s), fgets() affects what was printed above.
char *fgets(char * restrict s, int n, FILE * restrict stream) {
// code
s[i] = ThisAndThat();
// code
return s;
}
Let's now see how fgets() otherwise might be called:
char *p = malloc(80);
*p = '\0';
printf("Before <%s>\n", p); // "<>"
fgets(p, 80, stdin);
printf("After <%s>\n", p); // "<Hello World!>"
In this 2nd example, p is a "pointer to char". It is passed by value to fgets(). fgets() received, via s, a copy of p.
The central idea: fgets() does not know if it received an "address of the first element of an array" or a copy of a "pointer to char". In both cases, it treats s as a "pointer to char".
Let's assume fgets() did the following. Before s being changed, it affects the data pointed to by s. Then s, the pointer, changed. s is a local variable and this assignment does not change the calling routines variables buf nor p.
char *fgets(char * restrict s, int n, FILE * restrict stream) {
// lots of code
s[0] = '\0';
// more code
s = NULL;
return s;
}
Note: There are other issues such as passing functions as parameters and encapsulating arrays in structures to consider.
So, I saw this:
error:(NSError **)error
in the apple doc's. Why two stars? What is the significance?
A "double star" is a pointer to a pointer. So NSError ** is a pointer to a pointer to an object of type NSError. It basically allows you to return an error object from the function. You can create a pointer to an NSError object in your function (call it *myError), and then do something like this:
*error = myError;
to "return" that error to the caller.
In reply to a comment posted below:
You can't simply use an NSError * because in C, function parameters are passed by value—that is, the values are copied when passed to a function. To illustrate, consider this snippet of C code:
void f(int x)
{
x = 4;
}
void g(void)
{
int y = 10;
f(y);
printf("%d\n", y); // Will output "10"
}
The reassignment of x in f() does not affect the argument's value outside of f() (in g(), for example).
Likewise, when a pointer is passed into a function, its value is copied, and re-assigning will not affect the value outside of the function.
void f(int *x)
{
x = 10;
}
void g(void)
{
int y = 10;
int *z = &y;
printf("%p\n", z); // Will print the value of z, which is the address of y
f(z);
printf("%p\n", z); // The value of z has not changed!
}
Of course, we know that we can change the value of what z points to fairly easily:
void f(int *x)
{
*x = 20;
}
void g(void)
{
int y = 10;
int *z = &y;
printf("%d\n", y); // Will print "10"
f(z);
printf("%d\n", y); // Will print "20"
}
So it stands to reason that, to change the value of what an NSError * points to, we also have to pass a pointer to the pointer.
In C everything is pass by value. If you want to change the value of something you pass the address of it (which passes the value of the memory address). If you want to change where a pointer points you pass the the addres of the pointer.
Take a look here for a simple explanation.
In C, a double star is a pointer to a pointer. There are a couple of reasons to do this. First is that the pointer might be to an array of pointers. Another reason would be to pass a pointer to a function, where the function modifies the pointer (similar to an "out" parameter in other languages).
The double star (**) notation is not specific to initializing a variable in a class. It is simply a double indirect reference to an object.
float myFloat; // an object
float *myFloatPtr; // a pointer to an object
float **myFloatPtrPtr; // a pointer to a pointer to an object
myFloat = 123.456; // initialize an object
myFloatPtr = &myFloat; // initialize a pointer to an object
myFloatPtrPtr = myFloatPtr; // initialize a pointer to a pointer to an object
myFloat; // refer to an object
*myFloatPtr; // refer to an object through a pointer
**myFloatPtrPtr; // refer to an object through a pointer to a pointer
*myFloatPtrPtr; // refer to the value of the pointer to the object
Double pointer notation is used where the caller intends that one of its own pointers need to be modified by a function call, so the address of the pointer, instead of the address of the object, is passed to the function.
An example might be the use of a linked list. The caller maintains a pointer to the first node. The caller invokes functions to search, add, and remove. If those operations involve adding or deleting the first node, then the caller's pointer has to change, not the .next pointer in any of the nodes, and you need the address of the pointer to do that.
If it is anything like C then ** means a pointer to a pointer.