Why is my output 5 and 0 instead of 6 and 5 - c

Why my code output is 5 and 0, not 6 and 5?
I think I should get 6 and 5. I am a beginner.
#include <stdio.h>
int swap(int a,int b);
int main()
{ int x =5;
int y =6;
printf("%d %d\n",x,y);
int number[2]={swap(x,y)};
x=number[0];
y=number[1];
printf("%d %d\n",x,y);
return 0;
}
int swap(int a,int b)
{
return b,a;
}

There are several things wrong here.
First, you can't return multiple values in C, like you can in Python. return b, a; uses the comma operator, which evaluates both its operands and returns the second one. So this is equivalent to just return a;.
Second, your array initializer is only initializing the first element of the array. There's only one expression in the initialization braces, so that initializes number[0]. The remaining elements of the array are initialized by default to 0.
Combining both of these, it's equivalent to:
int number[2] = {y, 0};

I can see you are new to C programming. The problem is in your swap() function. You're using a language construct that does not exist in C, namely tuples. Check out pointers for a proper way to return multiple values from a function.

This function ...
int swap(int a,int b)
... returns one int, as its prototype says.
This statement ...
return b,a;
... involves C's comma operator ,, which evaluates its left-hand operand, discards the result, then evaluates to the value of its right-hand operand. Since evaluating b has no side effects in your case, that return statement is equivalent to
return a;
In C, it is valid to initialize an array with fewer explicit elements than the length of the array. For an automatic (local, non-static) array such as yours, as long as at least one element is initializer, all elements not explicitly initialized are implicitly initialized (to 0 in the case of int elements). Thus, for your implementation of swap(), this ...
int number[2]={swap(x,y)};
... is equivalent to
int number[2] = { x, 0 };
, which explains the output.

Here is a way to solve your problem.
#include <stdio.h>
void swap(int *a,int *b);
int main()
{
int x = 5;
int y = 6;
swap(&x, &y);
printf("post swap x = %d, y = %d\n", x, y);
return 0;
}
// No need to return anything, we change the x, y values using the pointer
// This is passing by reference. Instead of passing the value, we are
// passing the reference (i.e address of the variable). swap function can
// now directly access the values and change them
void swap(int *a, int *b)
{
int tmp;
printf("Swap got a = %d, b = %d\n", *a, *b); // Note: we access value of a pointer using * in front of the pointer varaible
tmp = *a;
*a = *b;
*b = tmp;
}
outputs:
bhakta: /tmp$ cc x.c
bhakta: /tmp$ ./a.out
Swap got a = 5, b = 6
post swap x = 6, y = 5

Related

Arrays & Passing By Reference in C

I am learning some of the basics of C, and am currently stepping my way through arrays and more specifically how passing by reference works. When the below code is run it returns 10 22. When I read through the code however, based on the last command it seems as though the variable a should return 22 instead of 10 (meaning the full output would be 22 22 instead of 10 22). Why would the variable a not update to 22 in this code?
#include <stdio.h>
void set_array(int array[4]);
void set_int(int x);
int main(void)
{
int a = 10;
int b[4] = { 0, 1, 2, 3 };
set_int(a);
set_array(b);
printf("%d %d\n", a, b[0]);
}
void set_array(int array[4])
{
array[0] = 22;
}
void set_int(int x)
{
x = 22;
}
Arrays are [loosely] "pass by reference". Actually, the array "decays" into an int *.
But, scalars are "pass by value".
In set_int, you set the function scoped copy of x but do not return it to the caller.
Here's the refactored code, with a "call by reference" example:
#include <stdio.h>
void
set_array(int array[4])
{
array[0] = 22;
}
int
set_int(int x)
{
x = 22;
return x;
}
void
set_int_byptr(int *x)
{
*x = 37;
}
int
main(void)
{
int a = 10;
int b[4] = { 0, 1, 2, 3 };
int c = 4;
#if 0
set_int(a);
#else
a = set_int(a);
#endif
set_array(b);
set_int_byptr(&c);
printf("a=%d b=%d c=%d\n", a, b[0], c);
return 0;
}
In C if you want to modify variable passed to function you need to pass the pointer to it:
examples:
int setval(int *obj, int value)
{
*obj = val;
return val;
}
void usage()
{
int x;
setval(&x, 22);
}
void *setpointer(void **ptr, size_t size)
{
*ptr = malloc(size);
return *ptr;
}
void usage1()
{
int *array;
setpointer(&array, 200*sizeof(*array));
}
First we need to get this out of the way, because I honestly believe it will make things less confusing - C does not pass any function arguments by reference, ever. C passes all function arguments by value. Sometimes, those values are pointers. This is not the same thing as pass-by-reference.
Among other things, pass-by-value means that any changes to a formal parameter are not reflected in the actual parameter. In your set_int function, x is a distinct object from a, and any changes to x do not affect a.
If we want a function to modify the value in a parameter, we must pass a pointer to that parameter:
void set_int( int *x )
{
*x = 22; // writes a new value to the thing x points to
}
int main( void )
{
int a = 10;
set_int( &a ); // foo writes a new value to a
return 0;
}
In the above code, we want the function set_int to update the variable a, so we must pass a pointer to a to the function.
x == &a // int * == int *
*x == a // int == int
Thus, writing a new value to the expression *x in set_int is the same as writing a new value to a in main. Any change to x itself is local to set_int.
Things get confusing when we add arrays to the mix. An array is not a pointer; however, unless it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T" and the value of the expression will be the address of the first element.
When you call set_array(b), the expression b "decays" from type "4-element array of int" (int [4]) to type "pointer to int" (int *), and the value of the expression is the same as &b[0].
Here's another confusing thing - in a function parameter declaration, array declarations of type T a[N] and T a[] are interpreted as T *a - a is a pointer to T, not an array of T. So your prototype
void set_array(int b[4])
is interpreted as
void set_array(int *b)
and what it receives is a pointer to the first element. As a practical matter, this means that any changes to array[i] in set_array are reflected in b, but this is fallout from how C specifically treats array expressions, not a difference in parameter passing mechanisms. The argument is still being passed by value, it's just that the argument is a pointer value that's the result of a well-defined conversion operation on array expressions.
You are doing 2 things over here:
1) Pass by value:
the function set_int(), its parameter is passed simply, without any address, which means it is pass by value, and any change made by this function set_int() will not be reflected in the calling function.
2) Pass by reference:
However, in the case of set_array(b), you are passing the array to the called function, and its base address will be passed (Means address of first element of b, that is &b[0]), hence this is pass by reference and any change is made to this value will be reflected in the calling function
which is the reason 22 is updated for b, but 22 didn't get update for a

How to swap 2 integers using pointers?

when I try to swap these two integers using pointers, I get segmentation fault.
Basically before I swap, x is assigned to 1 and y is assigned to 2. After I swap x is assigned to 2 and y is assigned to 1.
The program takes two integers x and y and is supposedly meant to swap them:
int swap(int x, int y){
int *swapXtoY;
int *swapYtoX;
*swapXtoY = y;
*swapYtoX = x;
}
Function swap is expecting both of its argument as int, but you are passing int *. Compiler should raise a warning about this.
It seems that you have no idea how pointers work in C. Your function is just assigning two ints to local variables. Function should be like:
int swap(int *x, int *y){
int temp;
temp = *x;
*x = *y;
*y = temp;
}
swap method should accept two pointer, instead of two integers.
Try following.
int swap(int* x, int* y){
int temp = *x;
*x = *y;
*y = temp;
}
You must pass variables by address to functions to change their value.That being said,your functions should expect pointers as well.Here is a generic function that can swap variables of any C data type:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Swap(void *x,void *y,size_t bytes);
int main(void)
{
int x = 3, y = 4;
Swap(&x,&y,sizeof(int));
printf("x now : %d\n",x);
printf("y now : %d\n",y);
return 0;
}
void Swap(void *x,void *y,size_t bytes)
{
void *tmp = malloc(bytes);
memcpy(tmp,x,bytes);
memcpy(x,y,bytes);
memcpy(y,tmp,bytes);
free(tmp);
}
Firstly, your function passes its arguments by value1, which makes it impossible for the function to make any lasting changes to them.
Secondly, the swap idiom consists of:
defining an intermediate variable, temp, which is initializes to one of the two variables, for example x.
assigning the value of the second variable,y to the first (saved in temp) variable x (now temp has value x and x has value y).
finally, assigning temp, to the second variable, y (now x has the value of y and vice versa).
In C code, this would look like:
void swap (int *x, int *y ) {
// dereference x to get its value and assign it to temp
int temp = *x;
// dereference x and assign to it the value of y
*x = *y;
// complete the swap
*y = temp;
}
Then to call the function:
// if the variables are not pointers
swap(&x, &y);
// if variables are passed via pointers
swap(x_ptr, y_ptr);
You might want to check the meaning of the dereference operator * or address-of operator &.
1. By value: it passes a copy of the passed variable, which prevents any change outside the function.

How to cast back to multidimensional?

How to cast back from void* ?
int *a[13][12];
void *b
int *c[13][12];
b = (void*) a;
c = (?????) b;
This
c = (int *[13][12])b;
says cast specifies array type
This
c = (int *[][])b;
says array type has incomplete element type.
Compiler is gcc (Ubuntu/Linaro 4.6.1)
In C, you cannot assign to an array, so since c is declared as an array of arrays of pointers to ints, you can't assign it directly.
You could however overwrite all of its items by assigning c[i][j] in turn inside a for loop, for example.
c and a are arrays not pointers, see above, you can use a pointer to a (2 dim) array like
int a[13][12] ={ 1,2,3 };
void *b = &a;
int (*c)[13][12] = b;
and all that without casts
You cannot assign directly to an array, or cast to an array type in C. However, since arrays decay to pointers, you can copy the data from a void * pointer (i.e.: memcpy) to an array and use it as an array, e.g.:
#include <stdio.h>
#include <string.h>
int main() {
int a1=1, a2=2, a3=3, a4=4;
int *a[2][2] = { { &a1, &a2 }, { &a3, &a4 } };
printf("%d %d %d %d\n", *a[0][0], *a[0][1], *a[1][0], *a[1][1]);
void *b;
b = (void*) a;
int *c[2][2];
memcpy(c, b, sizeof(c));
printf("%d %d %d %d\n", *c[0][0], *c[0][1], *c[1][0], *c[1][1]);
return 0;
}
Compiling and running the following program will give you:
1 2 3 4
1 2 3 4
However, c and a are two different arrays now.

pointers and functions

how to return more than one value from a function?
A function can only have a single return value. You could either pack multiple values into a compound data type (e.g. a struct), or you could return values via function parameters. Of course, such parameters would have to be passed using pointers to memory declared by the caller.
1
Declare method like this foo (char *msg, int *num, int *out1, int *out2);
and call it like this
int i=10;
char c='s';
int out1;
int out2;
foo(&c,&i,&out1,&out2);
Now what ever values u assign to out1 and out2 in function will be available after the function returns.
2
Return a structure having more than one members.
In C, one would generally do it using pointers:
int foo(int x, int y, int z, int* out);
Here, the function returns one value, and uses out to "return" another value. When calling this function, one must provide the out parameter with a pointer pointing to allocated memory. The function itself would probably look something like this:
int foo(int x, int y, int z, int* out) {
/* Do some work */
*out = some_value;
return another_value;
}
And calling it:
int out1, out2;
out1 = foo(a, b, c, &out2);
You cannot return more than 1 value from a function. But there is a way. Since you are using C, you can use pointers.
Example:
// calling function:
foo(&a, &b);
printf("%d %d", a, b);
// a is now 5 and b is now 10.
// called function:
void foo(int* a, int* b) {
*a = 5;
*b = 10;
}
Functions can return arrays or lists

Why do these swap functions behave differently?

#include <stdio.h>
void swap1(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
void swap2(int *a, int *b)
{
int *temp = a;
a = b;
b = temp;
}
void swap3(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
main()
{
int a = 9, b = 4;
printf("%d , %d\n", a, b);
swap1(a, b);
printf("%d , %d\n", a, b);
swap2(&a, &b);
printf("%d , %d\n", a, b);
swap3(&a, &b);
printf("%d , %d\n", a, b);
}
C has value semantics for function parameters. This means the a and b for all your three swap variants are local variables of the respective functions. They are copies of the values you pass as arguments. In other words:
swap1 exchanges values of two local integer variables - no visible effect outside the function
swap2 exchanges values of two local variables, which are pointers in this case, - same, no visible effect
swap3 finally gets it right and exchanges the values pointed to by local pointer variables.
You're swap2 function has no effect.
You are passing in two pointers. Inside the function, the (parameter) variables a and b are local to the function. The swap2 function just swaps the values of these local variables around - having no effect outside the function itself.
As Anon pointed out, swap1 has the same problem - you're just modifying local variables.
swap1 will not work because the function just copied the arguments, not affecting the variables in main.
swap2 will not work either.
swap1() and swap2() have an effect limited to the scope of the function itself: the variables they swap are parameters passed by copy, and any change applied to them does not impact the source variable of your main() that were copied during the function call.
swap3 works as it acts on the values pointed by the parameters, instead of acting on the parameters themselves. It is the only of the three that chage the value located at the memory adress in which your main()'s a and b variables are stored.
Just for fun, exchange values without the use of a temporary variable
x = x ^ y
y = x ^ y
x = x ^ y

Resources