Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C, how does arithmetic between a pointer and an array work?

Tags:

c

pointers

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 ?

like image 355
neel Avatar asked Oct 23 '12 12:10

neel


People also ask

How do pointers work with arrays in C?

When we allocate memory to a variable, pointer points to the address of the variable. Unary operator ( * ) is used to declare a variable and it returns the address of the allocated memory. Pointers to an array points the address of memory block of an array variable.

What is the relationship between pointers and arrays in C?

Array in C is used to store elements of same types whereas Pointers are address varibles which stores the address of a variable. Now array variable is also having a address which can be pointed by a pointer and array can be navigated using pointer.

What is the relationship between array notation and pointer arithmetic?

An array is represented by a variable that is associated with the address of its first storage location. A pointer is also the address of a storage location with a defined type, so D permits the use of the array [ ] index notation with both pointer variables and array variables.

How do pointers work with arrays?

Example 1: Pointers and Arrays In most contexts, array names decay to pointers. In simple words, array names are converted to pointers. That's the reason why you can use pointers to access elements of arrays. However, you should remember that pointers and arrays are not the same.


3 Answers

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)

like image 60
Mike Avatar answered Sep 27 '22 22:09

Mike


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.

like image 32
Maksim Skurydzin Avatar answered Sep 27 '22 22:09

Maksim Skurydzin


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.

like image 45
Preet Sangha Avatar answered Sep 27 '22 21:09

Preet Sangha