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.
Related
#include<stdio.h>
int main(){
int a1[]={6,7,8,18,34,67};
int a2[]={23,56,28,24};
int a3[]={-12,27,-31};
int *y[]={a1,a2,a3};
int **a= y;
printf("%d\n",a[0][2]);
printf("%d\n",*a[2]);
printf("%d\n",*(++a[0]));
printf("%d\n",*(++a)[0]);
printf("%d\n",a[-1][1]);
return 0;
}
When I run the above code output is 8,-12,7,23,8. But if i change the last 3 lines to
printf("%d\n",*(++a[2]));
printf("%d\n",*(++a)[1]);
printf("%d\n",a[-1][1]);
output is 8,-12,27,27,7. I'm unable to understand last printf statement. How does a[-1][something] is calculated ? And according to me *(++a)[1] should print 56 instead of 27 !
Pointers and array bases are in fact addresses in virtual memory. In C, they can be calculated into new addresses. Since the compiler knows the size of memory the pointer points to (e.g. int * points to 4 Bytes), a pointer +/- 1 means the address +/- the size (e.g. 4 Bytes for int).
The operator * means to get the value stored in the specified address.
Another trick here is the priorities of the operators. [] is calculated before ++.
If you understand what I mean above, your problem should be resolved.
according to me *(++a)[1] should print 56 instead of 27 !
++a increments a to the next int *, so after it pointed to y[0] equal to a1, it points to y[1] equal to a2. Then [1] in turn designates the next int * after y[1], i. e. y[2] equal to a3+1 (due to the preceding ++a[2]). Lastly, * designates the int which y[2] points to, i. e. a3[1] equal to 27.
I was playing with pointers in order to fully get the concept and then wanted to subtract two pointers expecting the distance between these two addresses or something, but apparently I was wrong, so here is my code.
int x = 5, y = 7;
int *p = &y;
int *q = &x;
printf("p is %d\nq is %d\np - q is %d", p, q, (p - q));
Why does the program output p - q is 1? Thank you.
It is undefined behavior. According to the standard (N1570):
6.5.6 Additive operators
....
9 When two pointers are subtracted, both shall point to elements of the same array object,
or one past the last element of the array object; the result is the difference of the
subscripts of the two array elements.
Note that when allowed, the result is the subscripts difference. So if pointers point to two sequential elements of the same type, the subtraction gives 1, regardless of the size of the type. (This is perhaps the reason why you get 1 in your concrete case.)
Your particular case is cause for undefined behavior since p and q point to unrelated objects.
You can make sense of p-q only if p and q point to the same array/one past the last element of the same array.
int array[10];
int* p = &array[0];
int* q = &array[5];
ptrdiff_t diff1 = q - p; // Valid. diff1 is 5
ptrdiff_t diff2 = p - q; // Valid. diff2 is -5
q - p is 5 in this case since they point to elements of the array that are 5 elements apart.
Put another way, p+5 is equal to q. If you start from p and step over 5 elements of the array, you will point to the same element of the array that q points to.
As an aside, don't use the format specifier %d for printing pointers. Use %p. Use %td for ptrdiff_t.
printf(" p is %p\n q is %p\n p-q is :%td", p, q, p-q);`
// ^^ ^^
See http://en.cppreference.com/w/c/io/fprintf for the valid format specifiers for the different types.
Pointer arithmetic works like that. It doesn't give you differences between two addresses. Instead it will show difference between two variables as if they are stored in an array. so, no matter if your variables (of same type ) are 4 bytes, 8 bytes or 1 byte, if stored in adjacent memory location their pointer subtraction will always result in 1 or -1.
The subtraction of 2 pointers give the distance in between the 2 variables.
For eg.
//let the address of a is 1000 then of a+1 will be 1004
int a[]={1,2,3};
int *p1=a;
int *p2=a+1;
printf("%u",p2-p1);
The result of this will be 1 not 4.
Same here in your case the the location of x and y are consecutive that is why the ans. is 1.
The formula used by pointer substraction is:
( p2 - p1 ) == ( addr( p2 ) - addr( p1 ) ) / sizeof( T )
with T being the type of both p1 and p2.
int array[10];
int* p1 = array + 2;
int* p2 = array + 5;
int* a = p2 - p1; // == 3
int* b = p1 - p2; // == -3
int a=5,b=6;
int *ptr=&a,*diff;
diff=ptr;
printf("%p\n",diff);
ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;
printf("%p\n",ptr);
printf("diff==%td\n",(ptr-diff)*sizeof(int));
(diff-ptr) will provide the distance between two variables, but will not provide the memory gap between two pointers.
Important: only the same type of pointer can be subtracted.
The subtraction of two pointers in array will give the distance between the two elements.
Let the address of first element i.e., is 1000 then address of second element a+1 will be 1004. Hence p1 = 1000 and p2 =1004.
p2-p1 = (1004- 1000) /size of int = (1004-1000)/4 =4/4 =1
#include <stdio.h>
int main(void){
int* p = NULL;
int y = 1;
p = &y;
printf("%p\n",p);
*(p+1) = 10;
printf("%p\n",p);
return 0;
}
outputs:
0x7ffe2368f2e4
0x7ffe0000000a
I do not know why p was changed here and the second one has "0000000a" which is 10 in the end, could you help me with that? thank you. I compiled it with gcc in linux.
The two variables y and p are allocated on the stack. Their storage is adjacent to each other, and looks like this:
y: <addr1> <val1> 4 bytes
p: <addr2> <val2> 8 bytes
Note that <addr2> is <addr1> + 4.
For your example, the actual addresses look like this:
y: 0x00007ffe2368f2e4 <value1> 4 bytes
p: 0x00007ffe2368f2e8 <value2> 8 bytes
After y = 1 and p = &y, the memory looks like follows:
y: 0x00007ffe2368f2e4 0x00000001 4 bytes
p: 0x00007ffe2368f2e8 0x00007ffe2368f2e4 8 bytes
p + 1 is value of p + sizeof(int), which is 0x00007ffe2368f2e4 + 4, which is 0x00007ffe2368f2e8, which is the address of p.
*(p + 1) = 10 sets 4 bytes at 0x00007ffe2368f2e8 to 10.
This is overwriting 4 bytes of a 8 byte value at 0x00007ffe2368f2e8, which is 4 bytes of the value of p.
0x7ffe 2368f2e4
0x7ffe 0000000a ------> this is the lower 4 bytes set to 10 i.e. 0xa
What cause the change of address the pointer points to?
TL;DR - undefined behavior.
To elaborate, in your code,
*(p+1) = 10;
invokes undefined behavior as you try to access a a memory out of bound. Kindly note, segmentation fault in only one of the many possible side-effects of UB.
Once your code invokes UB, nothing, absolutely nothing is guaranteed.
Also, FWIW, to print a pointer, you should be casting the pointer to void* before using that as an argument to %p.
As others have said, this statement invokes undefined behavior:
*(p+1) = 10;
Since prior to this statement, p contains the address of y, which is of type int. So the above statement writes to an area of memory which is not y.
As for an explanation of what actually happened, it appears that p appears right after y on the stack. So when you do *(p+1) = 10;, it writes to the sizeof(int) bytes after y on the stack, which happens to be where p lives.
Based on the fact that the initial value of p is 0x7ffe2368f2e4, that tells us that sizeof(int *) is at least 6 bytes, most likely 8 (i.e. 64 bit). With the value changing to 0x7ffe0000000a after the assignment, we see that the 4 low-order bytes of p were modified. This would make sense if sizeof(int) is 4 and you're working in a little-endian architecture. So the assignment ends up setting the first 4 bytes of p (the low order bytes) to the value 10 while leaving the rest (the high order bytes) unchanged.
That's what happened in your particular case. There is no guarantee that this behavior will be consistent across different machines, compilers, or operating systems. In other words, undefined behavior.
This statement
*(p+1) = 10;
changes the pointer because it overwrites the memory occupied by the pointer.
As you can see from the output values
0x7ffe2368f2e4 0x7ffe0000000a
this part 0x0000000a of the value 0x7ffe0000000a exactly equal to 10 that is assigned to the memory at address p + 1
So at the address p + 1 there is the pointer p itself.
If the sizeof( int ) is equal to 4 then 0x7ffe2368f2e4 is the address of y and 0x7ffe2368f2e8 is the address of the memory occupied by pointer p itself that is overwritten.
Another way to think about this is as y being like an array of 1 integer (that is only y[0] exists. The code:
*(a+i) equals a[i]
by definition. So, since:
p = &y
then:
*(p+1) equals y[1]
and accessing that which does not exist is undefined behavior. That means anything can happen, but the two most likely things are (1) you access some other variable (what happened to you) or (2) the program gets a segmentation fault.
What should be the value of y and why?
int x[] = { 1, 4, 8, 5, 1, 4 };
int *ptr, y;
ptr = x + 4;
y = ptr - x;
I think y should be 4*sizeof(int), but it is giving 4. Why ?
I think y should be 4*sizeof(int)
Good thinking, and guess what? It is giving 4*sizeof(int), but you're not looking at it right. ;)
When you're playing with pointers, you're looking at addresses, so let's check out some addresses
int x[] = { 1, 4, 8, 5, 1, 4 };
//Just for fun, what is the address of each element in the array?
printf("%#x, %#x, %#x, %#x, %#x, %#x\n", x+0, x+1, x+2, x+3, x+4, x+5);
ptr = x + 4;
printf("%#x - %#x\n", ptr, x); // Give us the address of ptr in hex
// and give us the address of x
y = ptr - x;
printf("%d\n", y);
Output:
x[0] x[1] x[2] x[3] x[4] x[5]
0xbf871d20, 0xbf871d24, 0xbf871d28, 0xbf871d2c, 0xbf871d30, 0xbf871d34
ptr x
0xbf871d30 - 0xbf871d20
4
So ptr is x+4 (which is really x + 4*sizeof(int) or x+16 in your case). And we're going to subtract from that x or the base address, so the actual math is 0x30 - 0x20 = 0x10 or in dec 16.
The reason you're seeing 4 on the output is because the compiler knows you're doing operations on int * so it's dividing that 16 by sizeof(int) for you. Nice hm?
If you want to see the actual value you need to do something like this:
int one, two;
...
one = (int)ptr; //get the addresses, ignore the "type" of the pointer
two = (int)x;
y = one - two;
Now y will give you 0x10(hex) or 16(dec)
It should be the number of int's between the address that points to the start of x and the address of x's 4-th element => 4.
From c99 standard:
6.5.6 Additive operators
9/ When two pointers are subtracted, both shall point to elements of
the same array object, or one past the last element of the array
object; the result is the difference of the subscripts of the two
array elements.
To find out more, try searching for pointer arithmetic.
Just apply some simple algebra
if
ptr = x + 4
and
y = ptr - x
therefore
y = (x + 4) - x
hence y = 4 + x - x
thus y = 4 + 0
y = 4
Edit: Addressing the comment
This is C, a ptr is just value of whatever size bits. Adding a number to it (except in the case of overflow) is just some integral number + another integral number (cast to the appropriate size), and thus removing the original number leaves a remainder. Since we only added 4 (smaller than an int) this means that there is no issue implicitly casting it to the y int.
if the operands of the binary '-'
are both pointers of same type it is evaluated as
(p-q)/sizeof(type of p or q)
in case the second operand is integer
then
p - sizeof(p)*q
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.