Consider the following programm,
#include<stdio.h>
int main()
{
int marks[]={20,65,45,68,89};
int *x,*y;
x=&marks[2];
y=&marks[4];
printf("%p\n%p\n"x,y);
printf("%p\n%p\n",y-x,*y-*x);
return 0;
}
When I want to print out the value of y-x, the console should give me a output equal to the difference between the addresses of the corresponding pointers. After all, we know that x and y are having addresses ('some integer value'). However it is not so. Why?
Pointer subtraction does not simply subtract the addresses but rather return the distance between two array elements (in terms of arary elements).
So y - x is not a pointer but an integer of the value 2 - and to printf it, you shold use %d formatting, now %p.
If you print the differences using %p, you will probably get something that's a bit hard to read.
The proper way is probably to use %lu, and cast:
printf("%lu\n", (unsigned long) (y - x));
Printing the integer quantity *y - *x as %p seems totally confused.
The result of subtraction of 2 pointers in the same array is the distance between those pointers in array, so y-x should equal 2 in your example.
To get difference between addresses cast them to some integer before substracting:
printf("%d",(size_t)y-(size_t)x);
y-x will evaluate to 2 - since the distance in between them is 2 ints.
If you print e.g. (char *) y - (char *) x you will get the distance in characters
the console must give me a output equal to the difference between the addresses of the corresponding pointers
... and it does. For me, it outputs 2. If you compare the addresses, you see that they are separated by 8 bytes, which is 2 ints, which is the answer you sought.
Related
I have problem solving this problem, so if anyne had a similar problem it would help me a lot.
short y[2][3]={{0123},{0x12345}},*p=y[1];
printf("01:%x\n", y);
printf("02:%x\n", p);
printf("03:%x\n", sizeof(y));
printf("04:%x\n", sizeof(y[0]));
printf("05:%x\n", sizeof(&y[0]));
printf("06:%x\n", sizeof(*p));
printf("07:%x\n", sizeof(p++));
printf("08:%x\n", *p++);
printf("09:%x\n", *p);
return 0;
Can anyone explain to me why the printout is like this?
01:61ff10
02:61ff16
03:c
04:6
05:4
06:2
07:4
08:2345
09:0
My opinion:
01:Prints the address where the array y begins.
02:Prints the address of the pointer, which points to the second element of the array. Since we have 2 * 3 elements that are of type short, each subsequent element of the zero element will increase by 6.
03:Since we have 2 * 3 elements, which is equal to 6, but the elements of the type are short, so it will print hexadecimal c
04:the number of elements in the zero position is 3, but they are of the short type, so it prints 6
05:prints the sizeof addresses of the first element of the array which is 4
06:I don't know why it prints 2 here
07:Prints the sizeof of the pointer address which is 4, it will increase after printing
08:I do not understand
09:I do not understand
Can anyone explain why it prints like this?
OK, let's see:
#01: The address of y.
#02: The value of p, which holds the address of y[1], which is the second element of type short[3]. The size of a short is apparently 2 on your system, so the offset to #01 is 6.
#03: The size of the array y, 2 * 3 * sizeof (short) give 12, in hex c.
#04: The size of the element y[0], which is of type short[3]. 6, as you found.
#05: The size of the address of y[0], and apparently the size of an address is 4 on your system.
#06: The size of the object that p points to. This is a short, so 2.
#07: The size of the expression p++, which is an address, so 4. And no, p is not incremented, since the expression is not evaluated.
#08: The value of the object that p points to, which is y[1][0]. Since the initializing value of 0x12345 is an int too big to be stored in a short, it is truncated to 0x2345. After reading the value, p is incremented.
#09: The element p points to, which is y[1][1]. It was initialized to 0.
Notes:
You should have got warnings from your compiler:
The mentioned initializer is truncated.
The format for pointers/addresses is %p.
The type of the result of sizeof might not match the format %x.
You should take warnings seriously, they are always a hint that you most probably made an error.
N6) Sizeof(*p) is size of datatype pointed by p. p is pointer to short: so 2 bytes.
N8) p is pointer to short, it`s pointing to array element y[1][0].
y[1] and y[1][0] have the same memory address.
All array elements are short, 0x12345 truncates to 0x2345 upon array initialisation. So output is 2345.
Also, p++ increases pointer value to point to next short y[1][1].
N9) Because of p++ in step N8, pointer now points to y[1][1], which was initialised to 0 (by default, because init value not provided) - output is 0.
I want to get the address difference between two elements in an array.
int vector[] = { 28, 41, 7 };
printf("%d\n", &vector[2]); // 1703652
printf("%d\n", &vector[1]); // 1703648
printf("%d\n", &vector); // 1703644
printf("%d\n", &vector[1] - &vector); // 1
The result I expect(Last Line) is 4 because the data type was int.
Further, each result of address has 4 differences.
But why is the result of
&vector[1] - &vector
1 and not 4?
And how do I get 4 by using subtraction operator?
pointer arithmetics in C language works on the type of the object. It does not matter how big the object is. The reference to the next object minus reference to the previous is always one object
So if we add 5 to the pointer it will point 5 objects ahead. If we increment the pointer it will reference the next object. It helps indexing and iterating across the objects.
When you printf the address (your format is wrong - you should use %p instead) it is printed in bytes. So the difference between the consecutive objects will be equal the size of the object (plus the optional padding).
And How to I get 4 by using subtraction operator???
Cast the pointers to the type which sizeof is one for example char.
(char *)&vector[1] - (char *)&vector
You can calculate the difference of pointers to byte-sized values by casting the pointers to char *:
printf("%d\n", (char*)&vector[1] - (char*)vector);
Pointers can only move in discrete steps.
int *p;
p = malloc(sizeof(int)*8);
Therefore, formally *(p+2) is calculated as *(p+2*sizeof(int)).
However If I actually code the above two, I get different results, which seems understandable.
*p = 123;
*(p+2) = 456;
printf("%d\n",*(p+2*(sizeof(int)))); \\0
printf("%d\n",*(p+2)); \\456
The question is, is this calculation implicit, done by the compiler at compile time?
The question is, is this calculation implicit, done by the compiler at
compile time?
Yes this is implicit, when you write ptr+n it actually advances forward n times as many bytes as size of pointee type (e.g. in case of int* - this is 4 bytes granted integer takes four bytes on your computer).
e.g.
int *x = malloc(4 * sizeof(int)); // say x points at 0x1000
x++; // x now points at 0x1004 if size of int is 4
You can read more on pointer arithmetic.
Therefore, formally *(p+2) is calculated as *(p+2*sizeof(int)).
No, *(p+2) is calculated as *(int*)((char*)p+2*sizeof(int)).
Even a brief look reveals that the only way for your statement to hold is if sizeof(int) == 1.
Hi I am new to C programming can anyone please tell me what this line of code would do:
i = (sizeof (X) / sizeof (int))
The code actually works with a case statement when it takes a value of bdata and compares it to different cases.
Generally, such a statement is used to calculate the number of elements in an array.
Let's consider an integer array as below:
int a[4];
Now, when sizeof(a) is done it will return 4*4 = 16 as the size. 4 elements and each element is of 4 bytes.
So, when you do sizeof(a) / sizeof(int), you will get 4 which is the length or size of the array.
It computes the number of elements of the array of int named X.
returns the length of the array X
it computes X's volume in memory divided by the size of an integer in your computer(2 bytes or 4 bytes). If i is integer than it is an integer division. If it is float and X has no even volume, it is real division.
int size can change. X depends on implementation. Division result depends on type of i.
All these means, it computes how many ints fit into X.
Besides common practice or personal experience there is no reason to think that this i = (sizeof (X) / sizeof (int)) computes the size of the array X. Most often probably this is the case but in theory X could be of any type, so the given expression would compute the ratio of the sizes of your var X and an int (how much more memory, in bytes, does your X var occupy with respect to an int)
Moreover, if X was a pointer to an array (float* X, the alternate way of declaring arrays in C) this expression would evaluate to 1 on a 32-bit architecture. The pointer would be 4 bytes and the int also 4 bytes => i = sizeof(X) / sizeof(int) (=1)
The following code manipulates pointers to point at the same location; I'm puzzled about why when I ran the code, the output didn't show value coinciding.
#include "stdio.h"
main()
{
int i=3,*x;
float j=1.5,*y;
char k='c',*z;
x=&i;
y=&j;
z=&k;
printf("\nAddress of x= %u",x);
printf("\nAddress of y= %u",y);
printf("\nAddress of z= %u",z);
x++;
y++;y++;y++;y++;
z++;
printf("\nNew Address of x= %u",x);
printf("\nNew Address of y= %u",y);
printf("\nNew Address of z= %u",z);
printf("\nNew Value of i= %d",i);
printf("\nNew Value of j= %f",j);
printf("\nNew Value of k= %c\n",k);
}
Output:
Address of x= 3219901868
Address of y= 3219901860
Address of z= 3219901875
New Address of x= 3219901872
New Address of y= 3219901876
New Address of z= 3219901876
New Value of i= 3
New Value of j= 1.500000
New Value of k= c
The new address of variable y and z are same. How can two variables have same address and et have different values?
Note: I used gcc compiler on Ubuntu 9.04
What you are printing is not the address of x/y/z, but rather the address they are pointing at. Then, by modifying the pointers (using ++) you eventually get y and z to point at the same address in memory.
Regarding the values - first thing you should notice that you don't actually change the values of j and k, and by the time you print those values the pointers no longer point to them.
Second thing is, even if you did print the value that the pointers point to, you would still get a different value since in one case the data would be interpreted as a float and in the other as a char.
Ah. The dangers of pointer arithmatic.
So y = &j sets pointer y to tha current address of float "j"
then you say y++ as you have defined y as a float pointer this is interpreted as add the length of a float variable to pointer y.
However you have only defined one floating point "j" so y is now pointing at whatever has been allocated after "j" -- in this case it happens to be the address of the "k" variable which was defined immediatly after -- but in practice it could be anything or nothing.
Had you defined "j" as an array of floating points it would have pointed to the second entry in the array equivalent to j[1]. Incendently C will also allow you to use j[1] even though you have not defined j as an array!
Incrementing pointers this way is only useful if your pointer points to an element in an array.
In fact, incrementing a pointer just increases its value by the size indicated by the type of the pointer, so:
incrementing a char-pointer will add 1 to the address
incrementing a long-pointer will add 4 to the address (on systems where a long is 4 bytes)
and so on
Also, while it is not the case in your examples, two variables may (appear to) have the same address but different values.
Assuming that you did:
void display_addr_and_val(const int& var){
printf("Addr:%p Val:%d\n",&var, var);
}
void main(){
int x=0;
int y=1;
display_addr_and_val(x);
display_addr_and_val(y);
}
.. you could theoretically end up with the same address shown for both x and y (if you turn on optimization) . Because the parameter of "display_addr_and_val" is a const reference, the code can be rewritten as:
void display_addr_and_val(const int& var){
printf("Addr:%p Val:%d\n",&var, var);
}
void main(){
int x=0;
display_addr_and_val(x);
int y=1;
display_addr_and_val(y);
}
now, in this version of the code, you may see that there is no overlap in the lifetime of "x" and "y". Which means that in fact the compiler may choose to use the same stack slot for both of them.
Granted, this doesn't happen very often, but there's not theoretical reason why it shouldn't happen - so the bottom line is that you should use extreme caution when you assume anything about the address of variables - especially local ones (e.g. don't assume that their addresses will be allocated in a given order, or that all distinct variables will use distinct addresses)
It's simple pointer math.
the address of the float is incremented at least by sizeof(float), (it should be 4 but you have an increment of 16, it depends on the hardware and the real size used to store floats) while the address of char is incremented by sizeof(char) (1)
you have that y + 16 = z + 1 which is not surprising, remembering that "the next float" (the "things" y now points to) is not indeed a float, but the memory location after the float and so it is for z (it'll point not to a char);
it just means that the float location is 15 bytes "before" the char location. I.e. y + 15 = z.
EDIT: with y I always mean the address of the float taken with &, and so for z...: i.e. before you incrmented them. y+16 is the incremented value of y (after you did y++) and z+1 the incremented value of z after z++.
EDIT 2: dumb me, I did not note that you increment y 4 times! so sizeof(float) is 4, 4*4= 16 ... ! and it is 4 on your machine too (as expected by IEEE for single precision fp numbers...) and so it means that y + (sizeof(float)*4 = z + sizeof(char) ... it still means y location is 15 bytes before z (the address of the char)