user25239
user25239

Reputation: 41

A strange result in my C code

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

Answers (4)

Matt Shank
Matt Shank

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

Vlad from Moscow
Vlad from Moscow

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

Keith Thompson
Keith Thompson

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 ints 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

merlin2011
merlin2011

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

Related Questions