开发者

C pointer arithmetic

开发者 https://www.devze.com 2022-12-17 15:08 出处:网络
Given this code: int *p, *q; p = (int *) 1000; q = (int *) 2000; What is q 开发者_如何学编程- p and how?It\'s actually undefined, according to the standard. Pointer arithmetic is not guaranteed to

Given this code:

int *p, *q;

p = (int *) 1000;
q = (int *) 2000;

What is q 开发者_如何学编程- p and how?


It's actually undefined, according to the standard. Pointer arithmetic is not guaranteed to work unless the pointers are both pointing to either an element in, or just beyond, the same array.

The relevant section of the standard is 6.5.6:9 (n1362 draft of c1x but this hasn't changed since c99) which states:

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.

You'll most likely get 250 if your int datatype is 4 bytes but there's no guarantee. Undefined behaviour (unlike implementation-defined behaviour) means just that, undefined. Anything can happen, up to an including the total destruction of a large proportion of space-time.

A refresher course:

  • Defined behaviour is what is mandated by the standard. Implementations must do this to be conformant.
  • Implementation-defined behaviour is left up to the implementation but it must document that behaviour clearly. Use this if you don't care too much about portability.
  • Undefined behaviour means anything can happen. Don't ever do that!


q - p is 250.

2000 - 1000 = 1000
1000 / sizeof(int) = 250

pointer arithmetic, assuming sizeof(int) is 4.


Edit: OK, to clarify. In C when two pointers are of the same type then the difference between them is defined the number of things of the pointed-to type between them. For example,

struct foo { int ar[1000]; } big[10];
char small[10];

struct foo *fs, *fe;
char *ss, *se;

fs = &big[0]; fe = &big[9];
ss = &small[0]; se = &small[9];

fe - fs == se - ss;

That is, the difference between the two pointers in this case is the number of array elements between them. In this case it is 0, 1, ... 8 or 9 elements.


q-p supposed to return how many steps with increment you should do to go from p to q. Which is 1000 / sizeof(int) and equals 250. Remember q++ will actually go to the next element of type int, not in the middle of it, so it should add 4 to the actual value of the pointer. Hence the result.


The answer: q-p is going to be 250, assuming you're on a machine where an int is 4 bytes.

The calculation is:

q - p = 1000 1000 / 4 (size of an int) = 250

The idea behind it:

The idea behind pointer arithmetic is that, if you have an int pointer to 1000 and an int pointer to 2000, and ask for the difference, you're not asking what's 2000-1000. What you're asking is, how many int's can I fit between the two.

This is very convenient for all sorts of operations, for example:

int *i = 100;
i++; // This is **not** 101, it is 104, cause you actually want the next place an int could fit in memory.

This especially comes in handy when dealing with arrays. An array of ints (defined int arr[10]) is basically treated like a pointer. When you write arr[5], the compiler translates it to *(arr + 5), i.e., add 5 to the int pointer called arr, and get the value at that address.

The reason this works, is because arr + 5 does not mean "add 5 to the value of arr", it means "add whatever is neceassary to the value of arr to go forward 5 ints", or, more precisely, "add 5 * sizeof(int) to the value of arr"


As p is pointing to an int and so q, q-p will be 1000.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号