Could someone please explain to me step by step what this code does?
int main(int argc, const char* argv[]) {
int numbers [2] [3] = {{1,2,3},{4,5,6}};
int (*num_ptr) [3]= numbers;
printf ("value is : %d\n",*(*(num_ptr+1)));
printf ("value is : %d\n",**num_ptr);
printf ("value is : %d\n",*(*num_ptr)+1);
printf ("value is : %d\n",*(*(num_ptr+1))+1);
//return (EXIT_SUCCESS);
}
It is easier to understand the code if you use array index notation. A[B] is the same as *(A+B), and vice versa, in all cases; with a special case being that A[0] is the same as *(A + 0), which is the same as *A if A is a valid pointer.
Applying this transformation, your code becomes:
printf ("value is : %d\n", num_ptr[1][0]);
printf ("value is : %d\n", num_ptr[0][0]);
printf ("value is : %d\n", num_ptr[0][1]);
printf ("value is : %d\n", num_ptr[1][0] + 1);
Hopefully you can take it from here.
The definition of num_ptr ensures that num_ptr[A][B] is the same as numbers[A][B]. Your program would be unchanged if the printf statements used numbers instead of num_ptr, because the array numbers decays to the same pointer value that num_ptr has.
*(*(num_ptr+1))
^^^^^^^^^^
skip the first row
No columns skipped after that
Ans = 4
**num_ptr
No rows or columns skipped
Ans = 1
*(*num_ptr)+1
^^^^^^^^^^^
no rows or column skipped
add 1 to the ans
Ans = 2
*(*(num_ptr+1))+1
^^^^^^^^^^^^^^^
skip first row, no columns skipped
add 1 to answer
Ans = 5
int (*num_ptr) [3]= numbers; declares num_ptr as a pointer to an array of 3 int and initializes it to the first element of array numbers. It is equivalent to
int (*num_ptr) [3]= &numbers[0];
num_ptr points to array numbers[0] and num_ptr+1 points to numbers[1]. *(num_ptr+1) dereferences num_ptr+1 and gives an array. As array decays to pointer to its first element in most context, *(num_ptr+1) will finally give &number[1][0]. So, *(*(num_ptr+1)) is equivalent to *(*(&number[1])) == *(&number[1][0]) == 4.
Similarly, **num_ptr will give 1, *(*num_ptr)+1) will give 1+1 =2 and *(*(num_ptr+1))+1 will give 4+1 =5.
First of all let's remove redundant parenthese inside the printf statement.
It will look like
printf ("value is : %d\n", **(num_ptr + 1) );
printf ("value is : %d\n", **num_ptr );
printf ("value is : %d\n", **num_ptr + 1 );
printf ("value is : %d\n",**( num_ptr + 1 ) + 1 );
num_ptr is declared like pointer to the first element of array numbers.
The elements of the array numbers are two on-dimensional arrays { 1, 2, 3 } and { 4, 5, 6 }
So expression *num_ptr yields the first one-dimensional array. In expressions with rare exceptions arrays are implicitly converted to pointers to their first elements. Thus this expression *num_ptr is converted to pointer to first element that is to 1 And **num_ptr gives the value.
As result this statement
printf ("value is : %d\n", **num_ptr );
outputs 1.
This statement
printf ("value is : %d\n", **num_ptr + 1 );
just adds 1 to the value of the prvious expression and outputs it that is 2.
As num_ptr is pointer to the first one-dimensioanle array then num_ptr + 1 is pointer to the second on-dimensional array { 4, 5, 6 }. Other calculations are the same as described above.
Thus statement
printf ("value is : %d\n", **(num_ptr + 1) );
outputs 4 and statement
printf ("value is : %d\n",**( num_ptr + 1 ) + 1 );
outputs 4 + 1 that is 5.
Related
I want to know what is the difference between all output? Why are there four different outputs?
#include <stdio.h>
int main()
{
int arr[]={1,2,3};
int*ptr=arr;
printf("%d\t %d\t %d\t %p\t %d \n",arr[0],arr[1],arr[2],ptr,*ptr);
*ptr++=-1;
printf("%d\t %d\t %d\t %p\t %d \n",arr[0],arr[1],arr[2],ptr,*ptr);
*++ptr=-2;
printf("%d\t %d\t %d\t %p\t %d \n",arr[0],arr[1],arr[2],ptr,*ptr);
(*ptr)++;
printf("%d\t %d\t %d\t %p\t %d \n",arr[0],arr[1],arr[2],ptr,*ptr);
return 0;
}
and this is the output
1 2 3 0x7ffe27496054 1
-1 2 3 0x7ffe27496058 2
-1 2 -2 0x7ffe2749605c -2
-1 2 -1 0x7ffe2749605c -1
Ok lets start.
Pointer stores memory address and giving a star(*) before a pointer variable denotes the value of that memory address.
int*ptr=arr;
In the above line you have copied the address of first index of the array(arr) into the ptr pointer.
So for the first print the pointer ptr value is the address of the first index of the array that means arr[0].
Then the second line:
*ptr++=-1;
Here you are post incrementing the value of ptr first, as ptr represents the address of the first index of the arr, so it will represent the address of second index of the array(arr[1]) in the next statement. but as it post incremented while setting the value -1 it would be set to array position 0(arr[0]).
Then the below line:
*++ptr=-2;
Here you are pre incrementing the value of ptr, so it would indicate the address of 3rd index of the array(arr[2]) and thus will set the value of arr[2] to -2.
Then the following line:
(*ptr)++;
Here you are incrementing the value of the address of ptr, as at that moment ptr is indicating the value of arr[2], so it will increment the value of arr[2] by 1.
Let me know if you don't understand any part. Happy Coding!
The statement
*ptr++ = -1;
is equivalent to
*ptr = -1;
ptr += 1;
And
*++ptr = -2;
is equivalent to
ptr += 1;
*ptr = -2;
Both of these should be quite easy to infer from your output.
Lastly
(*ptr)++;
which is equivalent to
*ptr += 1;
which increases what ptr is pointing to, but not ptr itself.
In the first line int*ptr=arr; means creating pointer to intger which hold the address of the first element array as arr=arr[0] so when print (ptr) will be the address of arr[0] and when print (*ptr) will print the value of the arr[0] which equle one
*ptr++=-1;
this line include post increment so firstly the value of arr[0] will be -1 then pointer will be incremented to include the address of arr[1] so when print arr[0] will be -1 ,,print (ptr) will be the address of the second element arr[1] and (*ptr) will print the value of arr[1] which is 2
*++ptr=-2;
this line include pre increment so firstly pointer will be incremented to include the address of arr[2] then the value of arr[2] will be -2 so when print arr[2] will be -2 ,,print (ptr) will be the address of the third element arr[2] and (*ptr) will print the value of arr[2] which is -2
finally
(*ptr)++;
this line will increment the value which pointer points to it as () has a high priority so (*ptr) means the value that pointer points to it and ++ will increment this value
I've written a code to find the number of elements in an integer array as follows:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[] = {2, 3, 5, 5};
int i;
for(i = 0; i < 4; i++)
{
printf("%d %d\n", &arr[i], arr[i]);
}
printf("%d", &arr[i - 1] - arr);
return 0;
}
The last printf prints 3 as opposed to 4 which is the number of elements in the array. Why does the code print one less than the no of elements in the array?
You pass the wrong format specifier to printf. So whatever output you get in the loop is the result of undefined behavior. To print a pointer correctly and portably you must use the %p specifier and pass a void*:
printf("%p %d\n", (void*)&arr[i], arr[i]);
The reason the last printf prints 3 (even though the format specifier is maybe wrong again), is because that's the offset between the the last cell in the array and the beginning. That's what you calculate, so remember that the last cell is indexed with offset 3.
The result of subtracting two pointers can be captured in the type ptrdiff_t. And to print that you'd need the %td format specifier, if we are to make your code more portable again:
printf("%td", &arr[i-1]-arr);
To calculate the array length, you'd need to subtract a pointer to "one passed the end" element of the array (don't worry, calculating that address is not undefined behavior) and a pointer to the beginning. Applying that to the print statement after your loop
printf("%td", (arr + i) - arr);
Which quite expectantly, is just i (4).
Your last printf need correction for specifiers as in your case the difference in first and last position address can easily fit in int but caan produce undefined behaviour so use td specifier as difference in address is of ptrdiff_t type. The problem is that how you calculate your length of array, keep in mind that indexing is done from zero that is if you have array length of 4, last index would be 3 and
array length according to your code is 3 - 0 = 3
but actually it should be 3 - 0 + 1 = 4
change your outside printf to
printf("%td",&arr[i-1] - arr + 1);
I hope this would help you. Also you printf in your for loop needs correct specifier as you are trying to print the address instead of int.
Out of curiosity, I ran this simple C program to see if I could index into a 2D array with one index:
#include <stdio.h>
int main(){
int a[][5] = {
{1,2,3,4,5},
{6,7,8,9,10},
{11,12,13,14,15},
{16,17,18,19,20},
{21,22,23,24,25}
};
printf("%d, %d\n", a[2][3], a[2*5 + 3]);
return 0;
}
Compiling with gcc -Wall warned me that the third parameter to printf was an int*,so I dereferenced it and recompiled. This time, I noticed that the second value printed was a number always in the range 32764 - 32767 (both inclusive), and usually 32764 or 32765. Is there a reason for this or is it just random data?
Edit: I changed the third parameter to printf to *a[2*5 + 3] after receiving the warning, sorry I didn't make it clear
Yes it is random data because you are trying to dereference the memory address which is not defined.
a[2 * 5 + 3] returns the address of 14th row which does not exist in your case. And *a[2 * 5 + 3] will be 1st element of 14th row.
Also as suggested by #iharob you should use %p instead of %d.
You are trying to print a pointer with the "%d" operator which is Undefined Behaviour. You must use "%p" for that.
What you want to do is possible but you are doing it wrong. You need to dereference the pointer again or you can cast to an int * like this
printf("%d, %d\n", a[2][3], ((int *) a)[2*5 + 3]);
you might also do this
printf("%d, %d\n", a[2][3], *(*a + 2*5 + 3));
This is a C code
int (*a)[3];
a is a pointer to an array of 3 integers
a=(int (*)[3])malloc(sizeof(int)*3);
note the Typecast used here; the number of elements must be specified in the typecast shown. Also, the brackets around the * is necessary.
printf("brrbrrbrr %d %d %d %d\n",&a,a,a+1,a+2);
*(a+0)[0]=40;
*(a+0)[1]=41;
*(a+0)[2]=42;
printf("noobnoob %d %d %d \n",a[0][0],*(a+0)[1],(*(*(a+0)+2)));
The output is:
brrbrrbrr -7077000 29278656 29278668 29278680
noobnoob 40 41 0
I am not getting why the last number is 0 instead of 42?
Indexation has higher precedence than dereferencing a pointer. Your assignments don't do what you want. They are evaluated like:
*((a+0)[0])=40;
*((a+0)[1])=41;
*((a+0)[2])=42;
If you want to keep your syntax, you shall use parenthesis like:
(*(a+0))[0] = 40;
(*(a+0))[1] = 41;
(*(a+0))[2] = 42;
The same applies for printing the second element of the array. *(a+0)[1] shall be (*(a+0))[1].
What you are looking for is
int (*a)[3] = malloc(sizeof(int) *3);
(*a)[0] = 40;
(*a)[1] = 41;
(*a)[2] = 42;
printf("%d %d %d\n",(*a)[0],(*a)[1],(*a)[2]);
a is a pointer to an array of 3 int members. So allocate memory for the pointer and store values as shown above.
If you want the address of where the values are stored then you should do
printf("%p\n",(void*)(a)[0]);
This is a question from Microsoft Test:
main()
{
int a[2][3]= { (1,2,3),(4,5,6)};
int (*ptr)[3] = &a[0];
printf("%d %d\n", (*ptr)[1],(*ptr)[2]);
ptr+=1;
printf("%d %d\n", (*ptr)[1],(*ptr)[2]);
}
Options given are:
segmentation fault
compiler error
bus error
run time error
I ran this code and I didn't get any of this. I got the following answer:
6 0
0 0
Can you please help me understand what's happening?
The main issue is this line:
int a[2][3]= { (1,2,3),(4,5,6)};
It is using parentheses instead of braces. The result of (1,2,3) is just 3, and the result of (4,5,6) is just 6. So this is equivalent to:
int a[2][3]= { 3,6 };
Which in turn is equivalent to
int a[2][3] = { {3,6,0}, {0,0,0} };
This line makes ptr point to a[0]:
int (*ptr)[3] = &a[0];
This line
printf("%d %d\n", (*ptr)[1],(*ptr)[2]);
is then equivalent to
printf("%d %d\n", (*&a[0])[1],(*&a[0])[2]);
which can be simplified to
printf("%d %d\n", (a[0])[1],(a[0])[2]);
or just
printf("%d %d\n", a[0][1],a[0][2]);
This line
ptr+=1;
makes ptr point to the next element of a, so it is equivalent to
ptr=&a[1];
so the next line simplifies to
printf("%d %d\n", a[1][1],a[1][2]);
The program effectively prints a[0][1], a[0][2], a[1][1] and a[1][2], so that's why you get 6,0,0,0.
Charles Baley points out that main() is missing the return type. This may be what they are getting at. The compiler would normally at least give a warning about that.
Are you sure you copied the text correctly?
(1,2,3) is an expression with two sequence or comma (,) operators; its value is 3. Likewise, the value of (4,5,6) is 6. This is the 6 that is being printed at a[0][1] (since ptr points to a[0] and you print (*ptr)[1]); the 0 is a[0][2], which has default initialization of 0. Then you increment ptr, pointing it to a[1], so you print a[1][1] and a[1][2], which also have default initialization of 0.