the code:
int arr[5] = {10, 20, 30, 40, 50};
printf("%lu %lu\n", *(&arr + 1), arr); // 6422036 6422016
printf("%lu\n", *(&arr + 1) - arr); // 5
Why the second printf prints 5 instead of 20?
There are two points in your interesting question :
How does operation on pointers work ?
What is the difference between arr and &arr ?
1 : How does operation on pointers work ?
Try the following code :
#include <stdio.h>
#include <inttypes.h>
int main(int argc, char **argv) {
int simpleInt= 10 ;
printf("Output 1 : %p %p \n", &simpleInt+1, &simpleInt); // 61FE20 and 61FE1C
printf("Output 2 : %lld \n", &simpleInt+1 - &simpleInt); // 1
printf("Output 3 : %lld\n", (uint64_t)(&simpleInt+1) - (uint64_t)(&simpleInt)); // 4
}
Output 1 : Clearly, the difference between the two printed pointer values is 4
Output 2 : You are performing operation on int *. 1 is added to an operand of type int * and after an operand of type int * is substracted. From an " int * point of view" (if I could simplify it like that), only one is added. So, the output is 1.
Ouput 3 : Each operands of the substraction are casted to a long long unsigned int. So the substraction is done on integers and not on pointers. The ouput is 4, as expected.
2. What is the difference between arr and &arr ?
Let's have a look to the following code
int arr[5] = {10, 20, 30, 40, 50};
printf("Output 1 : %p %p %p \n", arr, &arr, *(&arr) ); //Seems to be the same thing but NOT. int*, int*[5], int*, respectively
// printf("%lld\n", arr - &arr ); // compilation error : int * and int(*)[5]
printf("Output 2 : %lld\n", arr - *(&arr) );
//printf("%lld\n", &arr - *(&arr) ); // compilation error : int(*)[5] and int *
printf("Output 3 : %p %p %p \n", (arr + 1), (&arr + 1), *(&arr + 1) ); // +4, +20, +20
printf("Output 4 : %lld\n", *(&arr + 1) - arr);
printf("Output 5 : %lld\n", (uint64_t)(*(&arr + 1)) - (uint64_t)(arr));
Ouput 1 : The value are the same but not the type of arguments. And this point is very important. The name of an array is a pointer to its first element. In your case, your array is an array of int, so arr is a pointer to int : int*. &arr is the address of your variable arr which is an array of 5 integers. So the type of &arr is int(*)[5]. And the type of *(&arr) is int*
Output 2 : Some lines give compilation errors because of the explanation above. And you could do operations on the same pointer type : arr and *(&arr)
Output 3 : Depending which kind of pointer is incremented, +4 or +20 is obtained. +20 because 1 is added to an operand of type int(*)[5] : 5 * 4 (sizeof int = 4)
Output 4 & 5 : As, in the first point (operation on pointer), your are performing a substraction with int* as operand
Why the second printf prints 5 instead of 20?
Code is living on the edge.
&arr is the address of the array, so + 1 is the address of the next array: 5 int later. So far, this is good.
*(&arr + 1) de-references that address. So we get that next array. Not so good #RobertS supports Monica Cellio. An array passed to a ... function like printf() is converted to the address of the first element, an int *.
*(&arr + 1) - arr subtracts two pointers of the same type int * that are 5 int apart leading to difference of 5 of type intptr_t. Recall that pointer subtraction is the difference of the number of the referenced types (int in this case), not the difference of the pointer values. 5 not 20.
Code attempts to print a intptr_t as an unsigned long with "%lu", which might work, might not (UB). Not so good. Better to use "%td".
printf("%td\n", *(&arr + 1) - arr);
Related
I have a C program that uses pointers but I am not able to understand the output. Why is the first output 1 and the other is 210. They are both pointers to a 3 dimensional array.
I'm not able to find a solution
int main() {
char arr[5][7][6];
char (*p)[5][7][6] = &arr;
printf("%d\n", (&arr + 1) - &arr);
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
return 0;
}
the first output is 1 and the last is 210
C does pointer arithmetic in units of the pointed-to type.
In (&arr + 1) - &arr, &arr is the address of a char [5][7][6] (an array of 5 arrays of 7 arrays of 6 char). Then &arr +1 is the address of one char [5][7][6] beyond &arr and (&arr + 1) - &arr is distance from &arr to &arr + 1 measured in units of char [5][7][6], so the distance is one unit.
In (char *)(&arr + 1) - (char *)&arr), the two addresses are converted to char *, so the arithmetic is done in units of char. So the result is the distance from &arr to &arr + 1 measured in units of char. Since the distance from &arr to &arr + 1 is one char [5][7][6], it is 5•7•6 char, which is 210 char, so the result is 210.
Incidentals
Do not use %d to print the results of subtracting pointers. When two pointers are subtracted, the type of the result is ptrdiff_t, and it may be printed with %td, as in printf("%td\n", (&arr + 1) - &arr));.
To convert pointers to integers, it is preferable to use uintptr_t, defined in <stdint.h>, rather than unsigned.
To print unsigned values, use %u, not %d.
To print uintptr_t values, include <inttypes.h> and use "%" PRIuPTR, as in printf("%" PRIuPTR "\n", (uintptr_t) (p + 1) - (uintptr_t) p);.
First, it's not safe to use %d to print pointer differences, which have type ptrdiff_t (which is a signed version of size_t).
Ignoring that, you have the following declarations:
char arr[5][7][6];
char (*p)[5][7][6] = &arr;
When subtracting two pointers, result is divided by the size of the target (i.e., the inverse of what happens when you add an integer to a pointer, in which case the integer is scaled by the size).
For the first example:
(&arr + 1) - &arr
Here both &arr and &arr + 1 have type char (*)[5][7][6], so the size of what they point to is sizeof(char [5][7][6]). The pointer addition multiplies 1 by this size, and the pointer subtraction divides the difference by this size, canceling it out. So the result is 1, regardless of the target size.
For the second example:
(char *)(&arr + 1) - (char *)&arr
Here the pointer addition again multiplies 1 by sizeof(char [5][7][6]), which is sizeof(char)*5*7*6, i.e. 1*5*7*6 which is 210. But the subtraction divides by sizeof(char) which is 1. So the result is 210.
For the third example:
(unsigned)(arr + 1) - (unsigned)arr
The effect of the unsigned casts is similar to the effect of the char * casts in the previous example. However, in this one two pointers are arr and arr + 1. In this context, the array types "decay" to the pointer types char (*)[7][6]. The size of the pointer target is therefore sizeof(char)*7*6 i.e. 1*7*6 which is 42. So the result is 42.
Finally, for the last example:
(unsigned)(p + 1) - (unsigned)p)
Both p and p + 1 have type char (*)[5][7][6], so the target size is 210. The unsigned casts again result in straight address subtraction, with no division applied to the result. So the result is 210.
char (*p)[5][7][6] = &arr;
Here p is an array of pointers to chars, not a pointer to an array of chars.
printf("%d\n", (&arr + 1) - &arr);
& sign returns address. you are doing math on addresses not values! and anything plus 1 and minus itself will result in 1
(unsigned)p
this casting behavior is not guaranteed and is not safe to do. and you are not dereferencing your pointer anywhere.
You should read more about pointers, types and casting and operator priority before doing this.
I recommend this two videos by Brian Will:
the C language (part 2 of 5)
the C language (part 5 of 5)
I compiled this code and it gave the the value of '&x' 3 times. That is if &x = 2000 it printed 2036 three times. I want to know the reason for this behaviour assuming an integer requires 4 bytes of memory.
#include <stdio.h>
int main(void) {
// your code goes here
int x[4][3] = {0};
printf("%u %u %u", x+3, *(x+3), *(x+2)+3);
return 0;
}
What will be the output of this code
Anything can happen as the code provokes undefined behaviour by printing a pointer value using the conversion specifier for an unsigned.
To print pointer values use the conversion specifier p.
The address of an array and the address of its 1st element are the same. Pointers to them both however are of different type.
x as well as x + 3 are of type int (*)[3], that is pointing to an array of three ints. Assuming int to be of size 4, an array of three ints is of size 12.
Increasing x (a pointer to int (*)[3]) by three elements one ends up with an address 3 * 12 bytes beyond where x points to. This is called pointer arithmetic.
You're misusing a format specifier and invoking undefined behavior because of that. At that point, what happens is arbitrary and uninteresting.
If you want to print a pointer, use the %p specifier.
x is a pointer to an array of pointers. The array of pointers has 4 elements. Each of these four elements points to 3 integers.
Hence if x = 2000 then,
x[0] = 2000, x[1] = 2012, x[2] = 2024, x[3] = 2036.
Therefore,
x + 3 = 2036 (because x is an array pointer and it increases by 12 each time.)
*(x+3) = x[3] = 2036 again.
*(x+2)+3 = x[2] + 3 = 2024 + 3*4 = 2036 again.
Hence the output will be three same numbers.
I am in the process of learning C, and have begun exploring the world of pointers and pointer arithmetic. For example, in the following code snippet:
int nums[] = {1, 2, 3};
nums is an Array variable and acts like a pointer that points to the first memory location of the array. I wrote the following sample code and am trying to understand why I am getting the results that I am getting:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int nums[] = {1, 2, 3};
if(nums == &nums)
puts("nums == &nums");
else
puts("nums != &nums");
if((nums + 1) == (&nums + 1))
puts("(nums + 1) == (&nums + 1)");
else
puts("(nums + 1) != (&nums + 1)");
printf("nums: %i\n", nums);
printf("&nums: %i\n", &nums);
printf("nums + 1: %i\n", nums + 1);
printf("&nums + 1: %i\n", &nums + 1);
return 0;
}
I am getting that nums == &nums is true as expected; however, when I apply pointer arithmetic and add 1 to nums this result does not equal &nums + 1. In other words (nums + 1) != (&nums + 1) even though nums == &nums.
This is the output of the program that I get:
nums == &nums
(nums + 1) != (&nums + 1)
nums: 2345600
&nums: 2345600
nums + 1: 2345604
&nums + 1: 2345612
It appears that nums and nums + 1 are off set by 4 bytes; however, &nums and &nums + 1 are offset by 12. Why is it that this offset is by 12 bytes and not by 4?
The confusion is related to how in C, arrays implicitly decay into pointers in certain contexts.
The easier one to explain, nums + 1 effectively means &nums[0] + 1. nums[0] is type int, which is 4 bytes per element. Thus &nums[0] + 1 is 4 bytes after &nums.
As for &nums + 1, &nums is of type int(*)[3], which is 12 bytes per element. Thus &nums + 1 is 12 bytes after &nums.
Both expressions, (int*) nums and &nums have pointer types, but the types pointed to are different. You only can test them for equality in C, not C++.
The type of nums is int[3], that is, 'array of 3 objects of type int' and the type of (int*) nums is int*, that is, 'a pointer to int' . Adding 1 to (int*) nums means obtaining a pointer to an object of type int that follows nums[0]. In terms of addresses that means adding 1 * sizeof (int).
The type of &nums is int(*)[3], that is, 'pointer to an array of 3 objects of type int'. Adding 1 to &nums means obtaining a pointer to an object of type int[3] that follows nums. In terms of addresses that means adding 1 * sizeof (int[3]), that is, 3 * sizeof (int).
I created a pointer to pointer and a int array, but when I try to access the array via my pointer to pointer, it skips some elements and moves by two elements at a time (eg: from 1 to 3).
Here is my code:
int main(void) {
int c=10;
int p[5]={2,3,5,6,8};
int *x;
int **y;
x=p;
y=&p;
printf("p value is %d and p points to %d",p,&p);
printf("\n x is %d \n",x[1]);
printf("\n y is %d \n",y[0]);
return 0;
}
When I print y[1] it will print 5 instead of 3 and y[2] is printed as 8. I can't think of the reason. Can any one help me on this? Pointer x is is working fine and moves along the correct elements as x[0]=2, x[1]=3, x[5]=5.
also can any one explain why i get same value for p and &p
Okay, this question has been answered and an answer has been accepted, but even the accepted answer does not explain the weird results the original poster was seeing: why do y[1] and y[2] print 5 and 8? Here is the explanation.
Original poster: What output do you get from the following statements?
printf ("Size of integer: %zu\n", sizeof (int));
printf ("Size of pointer: %zu\n", sizeof (int*));
I'm going to bet that the output is:
Size of integer: 4
Size of pointer: 8
In other words, I'm guessing that you're compiling on a 64-bit machine where the size of an integer is 4 bytes and the size of a pointer is 8 bytes. Based on that assumption, here's what is happening.
p is an array. With a few exceptions, when used in any expression, the array's name "decays" to a pointer to its first element. Any time you access the value of p, therefore, it will yield the address of its first element.
&p is one of those exceptions to the rule about arrays "decaying" to pointers. The address-of operator, when applied to an array's name, returns a pointer to the entire array--not a pointer to a pointer to the first element of the array.
What this means is that p and &p have the same value, but they are semantically very different. You will get the same value when you print:
printf("p value is %p and p points to %p", p, &p); // use %p and not %d for addresses
However, this does not mean that p and &p refer to the same thing. p is the address of first element of the array, i.e., &p[0]. On the other hand, &p is the address of the entire array of 5 integers.
So when you define x and y as follows:
int* x = p;
int** y = &p;
x is assigned a pointer to the first element of the array; y is assigned a pointer to the entire array. This is an important difference!
There is, moreover, a mismatch between how y is declared, and the value you're assigning to it. &p is of type int (*) [5]; a pointer to an array of 5 int. y is merely a pointer to a pointer to a single int. Your compiler should give you a warning about this mismatch. Mine does:
Warning: incompatible pointer types assigning to 'int**' from 'int (*) 5'
This mismatch explains the weird results while printing values of y[1] and y[2]. Let's look at what's going on with the values.
As you know, array subscripts are offsets from the beginning of the array:
x[0] == *(x + 0)
So x[0] yields the first element of the array, i.e., 2. Similarly
x[1] == *(x + 1)
But x is a pointer to int. So what is actually happining in the addition x + 1? Remember how pointer arithmetic works. Adding an integer to a pointer means you're actually adding that integer times the size of the element pointed to. In this case:
x + 1 == x + (1 * sizeof(int))
Since sizeof(int) is 4 on your system, the value of x[1] is the next integer in the array, which is 3.
So then, when you print y[0], how is this evaluated?
y[0] == *(y + 0)
Hence, the value that is at the address pointed to by y, i.e., at the address of p, is printed. This is the first element of p, hence you get the result 2.
What happens when you print y[1]?
y[1] == *(y + 1)
But what is y? It is a pointer to a pointer to an int. So when you add 1 to y, the way pointer arithmetic works is it again adds 1 * the size of the type of the element pointed to.
y + 1 == y + (1 * sizeof (int*))
The size of an int* is 8 bytes, not four! So every time you increment y by 1, you're incrementing it by 8 bytes, or the size of two integers. Hence, when you dereference that value, you are getting not the next integer in the array, but the integer that is two away.
To explain more clearly: Let us assume that the array begins at element 1000. Then, because each int takes four bytes, the following is the case:
Address Element
-----------------------
1000 2
1004 3
1008 5
1012 6
1016 8
p == &p == x == y == 1000
*x == *y == 2
When you add 1 to x, you are adding 1 * sizeof(int), i.e., you are actually adding 4. So you get 1004, and *(x + 1), or x[1], gives you 3.
But when you add 1 to y, you are adding 1 * sizeof(int*), i.e., you are actually adding 8. So you get 1008, and *(y + 1) gives you the element at address 1008, or 5.
This explains the output you are getting. This is NOT, however, a reasonable way to code. You should not expect that the size of a pointer is always going to be 8 bytes. You should not assign an int (*) [] to an int**. You should not dereference a pointer to a pointer to an int and expect to get an int result. And always heed compiler warnings.
This at least gives a clean compilation and uses %p to print pointers:
#include <stdio.h>
int main(void)
{
int p[5]={2,3,5,6,8};
int *x = p;
int **y = &x;
printf("p value is %p and the address of p is %p and p points to %d\n", (void *)p, (void *)&p, *p);
printf("x[1] is %d\n", x[1]);
printf("y[0] is the address %p\n", (void *)y[0]);
printf("y[0][0] is %d\n", y[0][0]);
return 0;
}
Sample output (Mac OS X 10.8.4, GCC 4.8.1, 64-bit compilation):
p value is 0x7fff5a1a54d0 and the address of p is 0x7fff5a1a54d0 and p points to 2
x[1] is 3
y[0] is the address 0x7fff5a1a54d0
y[0][0] is 2
Remember array name can easily decays into pointer to first element in most expressions.
p[] array in memory is like (addresses are assumption):
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲
| | | | |
p p+1 p+2 p+3 p+3
After x = p;, x also pointer to first element.
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲
| | | | | |
| p p+1 p+2 p+3 p+3
|
x
+----+
| 200|
+----+
In expression y = &p; , &p is pointer of array of type int(*)[5] and y is int**. (you must getting a warning (or error) compile with -Wall).
Read: Difference between &p and p
Because value-wise both p and &p are same so address value of y is also same as p.
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲
| | | | | |
| p p+1 p+2 p+3 p+3
|
x y
+----+ +----+
| 200| | 200|
+----+ +----+
int* int**
Your first printf:
printf("p value is %d and p points to %d",p,&p);
Should be written as:
printf("p value is %p and p points to %p", (void*)p, (void*)&p);
// ^ ^
Use %p instead of %d because you are printing addresses also typecast to void* is necessary because %p expects void*. As I said value-wise p and &p are same both addresses are same.
Second printf:
printf("\n x is %d \n", x[1]);
Outputs: 3 as x points to first element in array x[1] == *(x + 1) == 3 (in my figures x + 1 == 204).
Third printf:
printf("\n y is %d \n", y[0]);
Note y type is int** so y[0] == *(y + 0) = *y value stored at y type of *y is int*.
So again because y[0] is int* you should use %p instead of %d.
But the above printf statement prints value of first element that is: 2.
Similarly y[1] prints 3 and y[2] prints 5.
Edit
When I print y[1] it will print 5 instead of 3 and y[2] is printed as 8.
No, It outputs as I explained above Check #codepade where sizeof(int) == sizeof(int*) probably in your system sizeof(int*) = twice of sizeof(int) (64-bit compiler) so when you add one you address next to next location.
As #WhozCraig commented: Try y = &x; You may have better luck. And print anything you're passing that should be a "pointer" with %p.
Correct your code.
I think you code cann't compile successfully.
The type of &p is char (*p)[10], but the type of y is char **,
cannot convert from 'char (*)[10]' to 'char **'
int main()
{
int (*x)[5]; //pointer to an array of integers
int y[6] = {1,2,3,4,5,6}; //array of integers
int *z; //pointer to integer
z = y;
for(int i=0;i<6;i++)
printf("%d ",z[i]);
x = y;
for(int i=0;i<6;i++)
printf("%d ",(*x)[i]);
return 0;
}
Both the above printfs print numbers 1 through 6.
If both "pointer to array of integers" and "pointer to integer" can do the same thing, do they have the same internal representation?
EDIT: This code does give warnings when compiled as pointed out by the answers below, however it does print the values correctly both the time on my x86_64 machine using gcc
Firstly, your code will not compile. The array has type int[6] (6 elements), while the pointer has type int (*)[5]. You can't make this pointer to point to that array because the types are different.
Secondly, when you initialize (assign to) such a pointer, you have to use the & on the array: x = &y, not just a plain x = y as in your code.
I assume that you simply typed the code up, instead of copy-pasting the real code.
Thirdly, about the internal representation. Generally, in practice, you should expect all data pointers to use the same internal representation. Moreover, after the above assignments (if written correctly), the pointers will have the same numerical value. The difference between int (*)[5] and int * exists only on the conceptual level, i.e. at the level of the language: the types are different. It has some consequences. For example, if you increment your z it will jump to the next member of the array, but if you increment y, it will jump over the whole array etc. So, these pointers do not really "do the same thing".
The short answer: There is a difference, but your example is flawed.
The long answer:
The difference is that int* points to an int type, but int (*x)[6] points to an array of 6 ints. Actually in your example,
x = y;
is undefined** behavior, you know these are of two different types, but in C you do what you want. I'll just use a pointer to an array of six ints.
Take this modified example:
int (*x)[6]; //pointer to an array of integers
int y[6] = {1,2,3,4,5,6}; //array of integers
int *z; //pointer to integer
int i;
z = y;
for(i = 0;i<6;i++)
printf("%d ",z[i]);
x = y; // should be x = &y but leave it for now!
for(i = 0;i<6;i++)
printf("%d ",x[i]); // note: x[i] not (*x)[i]
First,
1 2 3 4 5 6
Would be printed. Then, we get to x[0]. x[0] is nothing but an array of 6 ints. An array in C is the address of the first element. So, the address of y would be printed, then the address of the next array in the next iteration. For example, on my machine:
1 2 3 4 5 6 109247792 109247816 109247840 109247864 109247888 109247912
As you can see, the difference between consecutive addresses is nothing but:
sizeof(int[6]) // 24 on my machine!
In summary, these are two different pointer types.
** I think it is undefined behavior, please feel free to correct my post if it is wrong.
Hope this code helps:
int main() {
int arr[5] = {4,5,6,7,8};
int (*pa)[5] = &arr;
int *pi = arr;
for(int i = 0; i< 5; i++) {
printf("\n%d %d", arr[i], (*pa)[i]);
}
printf("\n0x%x -- 0x%x", pi, pa);
pi++;
pa++;
printf("\n0x%x -- 0x%x", pi, pa);
}
prints the following:
4 4
5 5
6 6
7 7
8 8
0x5fb0be70 -- 0x5fb0be70
0x5fb0be74 -- 0x5fb0be84
UPDATE:
You can notice that pointer to integer incremented by 4 bytes (size of 32 bit integer) whereas pointer to array of integer incremented by 20 bytes (size of int arr[5] i.e. size of 5 int of 32 bit each). This demonstrates the difference.
To answer your question from the title, from the comp.lang.c FAQ: Since array references decay into pointers, if arr is an array, what's the difference between arr and &arr?
However, the code you've posted has other issues (you're assigning y, not &y to x, and y is a 6-element array, but *x is a 5-element array; both of these should generate compilation warnings).
Who knows - this code exhibits undefined behavior:
printf("%d ",(*x)[i]);
Hope this code helps.
#include <stdio.h>
#include <stdlib.h>
#define MAXCOL 4
#define MAXROW 3
int main()
{
int i,j,k=1;
int (*q)[MAXCOL]; //pointer to an array of integers
/* As malloc is type casted to "int(*)[MAXCOL]" and every
element (as in *q) is 16 bytes long (I assume 4 bytes int),
in all 3*16=48 bytes will be allocated */
q=(int(*)[MAXCOL])malloc(MAXROW*sizeof(*q));
for(i=0; i<MAXROW; i++)
for(j=0;j<MAXCOL;j++)
q[i][j]=k++;
for(i=0;i<MAXROW;i++){
for(j=0;j<MAXCOL;j++)
printf(" %2d ", q[i][j]);
printf("\n");
}
}
#include<stdio.h>
int main(void)
{
int (*x)[6]; //pointer to an array of integers
int y[6] = {11,22,33,44,55,66}; //array of integers
int *z; //pointer to integer
int i;
z = y;
for(i = 0;i<6;i++)
printf("%d ",z[i]);
printf("\n");
x = &y;
for(int j = 0;j<6;j++)
printf("%d ",*(x[0]+j));
return 0;
}
//OUTPUT::
11 22 33 44 55 66
11 22 33 44 55 66
Pointer to an array are best suitable for multi-dimensional array. but in above example we used single dimension array. so, in the second for loop we should use (x[0]+j) with * to print the value. Here, x[0] means 0th array.
And when we try to print value using printf("%d ",x[i]);
you will get 1st value is 11 and then some garbage value due to trying to access 1st row of array and so on.
One should understand the internal representation of (*x)[i]. Internally, it is represented as
*((*x)+i), which is nothing but the ith element of the array to which x is pointing. This is also a way to have a pointer pointing to 2d array. The number of rows is irrelevant in a 2d array.
For example:
int arr[][2]={{1,2},{3,4}};
int (*x)(2);
x=arr; /* Now x is a pointer to the 2d array arr.*/
Here x is pointing to a 2d array having 2 integer values in all columns, and array elements are stored contiguously. So (*x)[0] will print arr[0][0] (which is 1), (*x)[1] will print the value of arr[0][1] (which is 2) and so on. (*x+1)[0] will print the value of arr[1][0] (3 in this case) (*x+1)[1] will print the value of arr[1][1] (4 in this case) and so on.
Now, a 1d array could be treated as nothing but a 2d array having only one row with as many columns.
int y[6] = {1,2,3,4,5,6};
int (*x)[6];
x =y;
This means x is a pointer to an array having 6 integers. So (*x)[i] which is equivalent to *((*x)+i) will print ith index value of y.