Reputation: 41
I have the following code in C:
int arr[] = {1,7,4,2,5,8};
int x = (&(arr[arr[1] - arr[4]]) - arr);
When I run this code, then x = 2.
But if I run this:
int arr[] = {1,7,4,2,5,8};
int a = &(arr[arr[1] - arr[4]]);
int b = arr;
int x = a-b;
Them x = 8.
Why do I get different values?
Upvotes: 3
Views: 114
Reputation: 158
In the first one, arr
is a pointer. In the second one, b
is an int.
In the first one, the subtraction results in 2, because the difference is two spots in the array.
In the second one, the subtraction results in 8, because each spot in the array takes up 4 bytes of memory. 4*2 = 8.
Upvotes: 1
Reputation: 310910
In your case 8
is equal to 2 * sizeof( int )
In the first code snippet there is used the pointer arithmetic while in the second code snipeet there is used the ordinary arithmetic with integer numbers.
In this expression
&(arr[arr[1] - arr[4]]) - arr
you deal with pointers. Between these two addresses ( &(arr[arr[1] - arr[4]])
and arr
) there are two
elements of the array and the first code snippet shows how many elements between these addresses. However the size of the memory that they occupy is equal to `8 and the second code snippet shows that.
Consider a simple example that it would be more clear
int a[2];
sizeof( a ) is equal to 8 that is 2 * sizeof( int ).
while sizeof( a ) / sizeof(int )
is equal to 2. It is the same as the value of the expression
( a + 2 ) - a
Upvotes: 4
Reputation: 263177
int b = arr;
The is an error (more precisely, a constraint violation). Since arr
is an array expression, it is, in most contexts including this one, implicitly converted to the address of its first element. Thus the experssion arr
, after the implicit conversion, is of type int*.
The initialization of a
is invalid for the same reasons.
There is no implicit conversion from int*
to int
.
Your compiler may implement such an implicit conversion as an extension (it's actually a very old C feature that's no longer defined), but if it's conforming it must at least issue a warning message.
In your first chunk of code, you're subtracting two int*
values that are point to locations 2 int
s apart. Pointer arithmetic is defined in terms of array indices.
In your second (invalid) chunk of code, if the compiler permits you to store an int*
value in an int
object, it will probably store the raw memory address. Depending on the addressing scheme used by your system, and depending on the size of int
(probably 4 bytes on your system), it's likely that the subtraction effectively computes the difference in bytes between the two pointers.
If you see warnings when you compile this code, you should pay attention to them, and you should definitely mention them when asking about it. If you don't see warnings, you should find out how to encourage your compiler to warn about bad code.
If you really want to compute the distance in bytes between two addresses, you can convert both pointers to char*
:
int arr[] = {1,7,4,2,5,8};
int *p1 = &arr[0];
int *p2 = &arr[2];
char *cp1 = (char*)p1;
char *cp2 = (char*)p2;
printf("p2 - p1 = %d\n", (int)(p2 - p1));
printf("cp2 - cp1 = %d\n", (int)(cp2 - cp1));
The first line should print 2
; the second should print the value of 2 * sizeof (int)
.
Upvotes: 2
Reputation: 75545
When you do arithmetic with pointers, the result is the number of units of the array of type.
When you do arithmetic with integers, the result is the literal number of bytes difference.
Upvotes: 0