Passing an array into a function in C - c

Consider the following C program:
#include <stdio.h>
void swap(int []);
int main(void) {
int a[3] = {1, 2, 3};
swap(a);
printf("%d %d %d\n", a[0], a[1], a[2]);
swap(&a[1]);
printf("%d %d %d\n", a[0], a[1], a[2]);
return 0;
}
void swap(int x[]) {
int temp = x[0];
x[0] = x[1];
x[1] = temp;
}
Can anyone explain why the following code gives an output
2 1 3
2 3 1
rather than
2 1 3
1 2 3
I understand that swap(a) swaps a[0] and a[1]. But I'm not so sure how swap(&a[1]) works. In both cases we are passing the array a into the function swap, are we not? So my hypothesis was that swap(&a[1]) should again swap a[0] and a[1], giving us back the original order 2 3 1.
EDIT: This code was written as intended. I just wanted to see what happens if we pass an address of an element other than the first element into the function. Apparently if I pass &a[n] into the function, it disregards all elements before a[n] and treats a[n] as the first element?

Your swap function takes and address of an integer as input and swaps element at that address with element at next address.
swap(a) is same as swap(&a[0])
It will swap element at index 0 with element at index 1.
Now your array becomes {2,1,3}
swap(&a[1]) swaps element at index 1 with element at index 2.
So your array now becomes {2,3,1}
Remember when you pass an array actually you are passing address of element at index 0 (&a[0]).

Because when you swap first time you sent an array starting with 0 index then it exchanges 0th and 1st index values means at first swap, array becomes {2,1,3} then again you sent this array starting with 1 index means you sent only two values {1,3}, then that values gets exchanges. In this case x[0] = 1 & x[1] = 3, that is why the output came as {2,3,1} here 2 remains as it is.

In the first call swap(a); you are passing the entire array (actually a pointer to the first element.) So you are swapping elements 0 and 1, which are 1 and 2, respectively, therefore your first output is 2 1 3.
In the second call swap(&a[1]); you are passing the address of the second element in the array, and in your swap function you are therefore swapping the second and third elements, at indices 1 and 2, which are 1 and 3, respectively. That's why your answer after the second iteration is 2 3 1.
Possibly what you meant was
swap(&a[0]);
This will swap the values at indices 0 and 1, which will give you the desired output of 1 2 3.

In your code before the first println statement you are passing a complete array to the parameter of the fuction but in the next you are just passing a single value of location of a[1] which make bit confusing for the function because it has only a single value to swap or it might be as first you passed a zero(0) index or the array to swap with the next time you pass first 1 index of array to swap with which means [1,3 to swap] so pass complete in next statment as this
swap(a);
printf("%d %d %d\n", a[0], a[1], a[2]);
swap(a);
printf("%d %d %d\n", a[0], a[1], a[2]);
return 0;
this will generate your desire answer

Related

Two dimension array dereferencing not working

Hello I am learning c in school and having a little confusion on this problem.
That is,
b is two d array, and I am trying to implement around printing values and the adress,
but why is *(b+1) giving the same thing as b+1?
I thought *(b+1) would give the value of the first element of the second row.
and if I change printf("%p\n", *(b+1)) to printf("%d\n", *(b+1)), it just gives a garbage value.
Why is it working like this?
I appriciate any feedback! thank you
int main()
{
int b[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
printf("b:\n");
print_2d_array(3, 4, b);
printf("\n");
printf("%p\n", b);
printf("%p\n", *(b+1));
printf("%p\n", b+1);
return 0;
}
Output is like this,
b:
0 1 2 3
4 5 6 7
8 9 10 11
0x7ffeecee6730
0x7ffeecee6740
0x7ffeecee6740
The question you have asked essentially boils down to a question about the nature of an array and the address of an array, which is a fairly well covered topic (see this for example). However, you likely confused yourself with the pointer arithmetic, so this answer tries to clarify some of that.
In C, when array object is used in an expression, its value and type becomes the same as the pointer to its first element.
In your case, you have:
int b[3][4] = { /* ... */ };
/* ... */
printf("%p\n", *(b+1));
printf("%p\n", b+1);
If we consider the last print statement,b in the expression b + 1 becomes the same as &b[0] + 1, and this would be the same as &b[1].
When we consider the print statement before the last one, we note that *(b+1) is defined to be the value b[1]. However, the result of that expression is an array of 4 int. That array now takes on the value and type of its first element, which would be &b[1][0].
Since you need to be able to find the address of the first element of an array from the array itself, the address of an array, &b[1], has the same pointer value as the address of its first element &b[1][0].
However, &b[1] and &b[1][0] have different types. The former is a pointer to an array, while the later is a pointer to an int.
For additional information, I encourage you to read the linked question at the top of this answer for more about arrays and the address of arrays.
*why is (b+1) giving the same thing as b+1?
The output address is numerically same but their type is different.
The type of *(b+1) is int [4] whereas the type of b+1 is int (*)[4].
*(b+1), when used in an expression, will convert to address of first element of second row1):
*(b + 1) -> b[1] -> ((b[1]) + (0)) -> &(*((b[1]) + (0))) -> &b[1][0]
and b+1 will give address of second row.
Address of an array and address of first element of that array are numerically same but their type are different.
*I thought (b+1) would give the value of the first element of the second row.
*(b+1) will give the second element of 2D array b which is nothing but a 1D array of 4 integers.
To access the first element of second row using *(b+1), you can do:
(*(b+1))[0]
To access the second element of second row using *(b+1), you can do:
(*(b+1))[1]
third element ....
(*(b+1))[2]
and so on .....
Note that *(b+1) is equivalent to b[1]1). So,
(*(b+1))[0] is equivalent to b[1][0]
(*(b+1))[1] is equivalent to b[1][1] .. and so on
Hope this clarifies your doubt.
1 ) From C Standards#6.5.2.1
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))..

I am not sure how the array of the code is being traced?

I don't understand how the array is being traced. I feel like I know it but then I mess it up again. I get how the values are being swapped but I am still getting confused. I wrote my questions as comments besides my code. Can someone help me trace that part?
#include <stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
int i,j,temp;
for (j=1; j<5; j++)
for (i=0; i<5-j; i=i+2)
{
printf("%d %d\n",i,i+j); //I got this part right
temp = a[i]; //from here I get confused
a[i] = a[i+j]; //how is the addition inside working??
a[i+j] = temp; //temp = the index's value
}
for (i=0; i<5; i++)
printf("a[%d] = %d\n",i,a[i]);//what is i supposed to be here??
}
Output:
0 1
2 3
0 2
2 4
0 3
0 4
a[0] = 2 //from here on I get lost
a[1] = 1
a[2] = 5
a[3] = 4
a[4] = 3
Why don't you print your whole array in every loop, that way you can see how values are moving, for example in step in you swap 0,1 element so array is {2,1,3,4,5}, then 2,3 so {2,1,4,3,5}, then 0,2 so {4,1,2,3,5} , 2,4,=> {4,1,5,3,2}, 0,3 {3,1,5,4,2},0 4 {2,1,5,4,3}
I am guessing you don't know much about C programming. So here is a bit about arrays:
An array (here: int a[5]={1,2,3,4,5}) is contiguously allocated blocks of memory.
An array a[n] is of size 'n'(stores n values of array type, here int) and is index from 0 to n-1. Meaning each of the n values are accessed from a[0] to a[n-1].
There are multi-dimensional arrays (read it up!).
The logic given here:
temp = a[i]; //temp gets a[i]'s value and not the value of i
a[i] = a[i+j];
a[i+j] = temp;
This is the standard swap(a,b) operation using a temporary variable temp. Just that 'a' and 'b' here are elements of an array.
The loops are designed in such a way to access different elements of the array in each iteration. This shuffles the array.
So obviously:
printf("a[%d] = %d\n",i,a[i]); // i here is the index used to access a's ith element
I found out what I was doing wrong. I was simply trying to do the math and change that position's value. I have to open up space and move the old number out to put the new number in. Then the old number will go to empty space that's left. It's actually just simply swapping but it helps to see it this way better.
So in {1,2,3,4,5}, if I try to put a[3]=4 in a[1]=2, the value 4 will go to a[1].
a[1] which had 2 will have to get out and a[3] which had 4 will move in.
The 2 that was out will go in the place where 4 was before in a[3]=2.
So now a[1]=4 and a[3]=2.
So the swapped array will now look like {1,4,3,2,5}

pointer and multidimensional array

i want to print the value which contain in the multidimensional array.I know that if we write something like arr[3][4] then arr[0] is the pointer to the first element in the that multidimensional array.
I want to ask why this code give me garbage value after the program print the number containing in the multidimensional array?
this is the code:
#include <stdio.h>
#define ROW 3
#define COLL 4
int main(void) {
int arr[ROW][COLL]={{1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
int *ptr;
for(ptr=arr[0];ptr<arr[ROW]+COLL;ptr++){
printf("%d ",*ptr);
}
printf("\n");
return 0;
}
this is the result when i compile the above code:
1 2 3 4 5 6 7 8 9 10 11 12 -1079481492 134513936 0 -1079481352
but after changing the for loop to the following:
for(ptr=arr[0];ptr<=arr[ROW-1]+COLL-1;ptr++)
the code work and give the exact number which contain in the multidimensional array.
Because arr[ROW] is an out-of-bounds access. The last valid position in arr is arr[ROW-1]. Thus the first version of your code invokes undefined behaviour.
The pointer to the last element is
arr[ROW-1] + COLL - 1
So you loop should be
for (ptr = arr; ptr < arr[ROW-1] + COLL; ptr++) {
Elements of an array are indexed from 0 so the last element in your matrix is arr[ROW-1][COLL-1].
When your pointer reaches arr[2] + COLL there is no such element because the second coordinate of the last element in last row is [COLL-1].
Elements of an array are stored in 1D so arr[0] + 4 is acctualy arr[1][0].
When you increment ptr++ it tells the compiler to access the next memory location after the current. So, when ptr points to a[0] + 4 it works because the compiler access the fifth value after a[0][0] which is actually the first value in the next row, arr[1][0], because their memory locations are next to each other.
When your ptr points to arr[4] + i, i = 0, 1, 2, 3 you get bad output because those elements are not in your array.
Because your first element, 1, is at arr[0]+0,
5 is at arr[1]+0,
9 is at arr[2]+0,
10 is at arr[2]+1,
11 is at arr[2]+2,
and 12, which is the last element of your array is at arr[2]+3.
but your for loop keeps moving even after the array ends, that is, until the memory location arr[3]+4 is reached. Giving you four garbage values because we have stored nothing in the memory after arr[2]+3.
so the for loop should be like:
for (ptr=arr; ptr <= arr[ROW-1]+COLL-1; ptr++);
which is equivalent to:
for (ptr=arr[0]; ptr <= arr[ROW-1]+COLL-1; ptr++);
as arr[0] and arr point to the same location in memory.
NOTE- try reading how memory is allocated in arrays of multiple dimensions.

Please explain the difference

i have a program about 2-D arrays
base adress is 8678
#include<stdio.h>
#include<conio.h>
main()
{
int arr[3][3]={
{83,8,43},
{73,45,6},
{34,67,9}
};
printf("%d ",&arr+1); //points to 8696
printf("%d ",arr+1); //points to 8684
return 0;
}
what is the difference between arr+1 and &arr+1?
Well, they're different things. arr decays in most contexts to a pointer to the first element of your array - that means a pointer to the first 3-element row in your 2D array: type int (*)[3]. arr + 1, then, points to the second row in the array.
&arr is the address of the array itself (type int (*)[3][3]), so &arr + 1 points to memory just past the end of the entirety of your 2D array.
You can confirm this behaviour easily by printing differently. Specifically, printing the offsets to the new pointers rather than the values themselves will help clear things up. The output from your program from these print statements:
printf("%ld\n",(intptr_t)(&arr+1) - (intptr_t)arr);
printf("%ld\n",(intptr_t)(arr+1) - (intptr_t)arr);
Will be the decimal offsets to &arr+1 and arr+1 respectively. Here's the output from a test run I just made:
36
12
36 matches up: 3 rows × 3 columns × 4 bytes per entry = 36 bytes. So does the 12: 1 row × 3 columns × 4 bytes per entry = 12 bytes.
Note - you're also printing pointers using %d, which is wrong. You should probably be using %p for that.
You can figure this out with the help of this equivalence: X[Y] === *(X+Y)
Since *(arr+1) === arr[1], arr+1 === &arr[1]
Similarly, &arr+1 === &((&arr)[1])
What is (&arr)[1]? Well, (&arr)[0] === *&arr === arr,
that is, the 3x3 array itself, so (&arr)[1] is the 3x3 array following that,
and &arr+1 === &((&arr)[1]) is the address of the 3x3 array following &arr ... a pointer to the byte just past the entire array.
Arr+1 gives the next element in an array while &arr +1 gives the address of next array of integers
array + 1 means the array[1] 's address and it costs 3 int memory.
&array + 1 means the address of array[0] add 1;

Question about a recursive function?

I have a recursive function from a C book as follows:
void print(int a[], int n)
{ if (n<=0) return ;
printf("%d\n", a[0]);
print(&a[1], n-1);
}
I have run and this function prints all the element of the specified array. But I really do not understand how this function works so that I can print all elements of an array.
Can anyone give me a clear explanation, please?
&a[1] is the address of the second element of the array, which is effectively the address of the portion of the array after the first element. So after printing the first element of the parameter array,
print(&a[1], n-1);
passes itself the remaining portion of the array, decreasing the length by one as well.
For example, if you call print with the array {1, 2, 3, 4, 5} and n == 5, the chain of events and calls is the following:
print the first element (1)
call itself with the remaining portion of the array, i.e. {2, 3, 4, 5} and n == 4
print the first element (2)
call itself with the remaining portion of the array, i.e. {3, 4, 5} and n == 3
print the first element (3)
call itself with the remaining portion of the array, i.e. {4, 5} and n == 2
print the first element (4)
call itself with the remaining portion of the array, i.e. {5} and n == 1
print the first element (5)
call itself with the remaining portion of the array, i.e. {} and n == 0
n<=0 -> return
return
return
return
return
return
This function takes as arguments the remaining part of the array and how many elements it contains. Every time you print the first element and then call recursively of the remaining part. Here is an example:
array: 1, 2, 3, 4, 5, 6; N = 6
array: 2, 3, 4, 5, 6; N = 5
array: 3, 4, 5, 6; N = 4
array: 4, 5, 6; N = 3
array: 5, 6; N = 2
array: 6; N = 1
array: ; N = 0 return;
Arrays are basically pointers to the start of the first element, so you code is essentially this:
void print(int *a, int n)
{ if (n<=0) return ;
printf("%d\n", *a);
print(a+1, n-1);
}
The recursive call is passing in a pointer to the next item in the array and decreasing the count, which is your used in your recursive termination condition.
So it does the following:
Check if there are any elements in the array, if not, just return.
Print the first element in the array since we know we have atleast one.
Calls itself again pointing to the 2nd element in the array, and subtracting 1 from the size, thus starting at #1 again.
A good way to understand recursion IMHO is to run the code in a debugger, and watch the call stack and variables.
How do you print a zero-sized array? Easy: you don't
That's your if (n<=0) return;
How do you print an array with 1 element? Easy: just print the element and remove it from the array and print the resulting zero-sized array as before
That's your printf("%d\n", a[0]);
How do you print an array with 2 elements? Easy: print the first element and remove it from the array and print the resulting one-sized array as before
That's your print(&a[1], n-1);
How do you print an array with N elements?
Easy: print the first element, remove it from the array, and print the resulting smaller array
If n is zero (or less), it does nothing, so recursion stops. If n > 0, then it prints a[0] and calls itself recursively with n-1 for n (so that goes to 0 as the recursion proceeds) and &a[1] for a, i.e. it increments the pointer a in each recursive call. Remember that an array argument in C is syntactic sugar for a pointer argument.
So, the code you posted is equivalent to:
void print(int *a, int n)
{
if (n > 0) {
printf("%d\n", *a);
print(a+1, n-1);
}
}
If you can verify to yourself that the following algorithm works to print an array, you should be able to understand why the C code works, since it's a direct translation.
To print n elements of an array:
If you're asked to print no elements, just stop.
Otherwise:
Print the first element, and then
Print n-1 elements of the rest of the array (using this same recipe).
it is equivalent to a loop:
int i ;
for (i = 0 ; i< n ; i++) {
printf("%d\n",a[i]);
}
why? well, the recursion always looks at the first element and prints it, and them advances to the next element by looking at the array from the 2nd element (which will now be the 'first', in the next iteration).
your stop condition is when no more elements are left - i.e. an array of length 0.
The function accepts an array and the length of the array.
if(n<=0) return;
If the length of the array is <=0 the function returns.
printf("%d\n", a[0]);
The first element of the array, element 0 is printed.
print(&a[1], n-1);
&a[1] gets a pointer to the first element of the array. Arrays and pointers are usable interchangably so when this is passed to the function the function can treat it as a new array, starting from the second element of the previous array, and with a length one less.
Each call to print do this :
print the n-th element of the array a and decrement the remaining elements (n) count to print.(Look at n like it means: how many elements remain to print).
Call it self decrementing (n - 1 : one less element to print) passing a pointer to the second element of the array (&a[1]) because the first element (a[0])has already be printed.
What exactly don't you understand?

Resources