3

Edit: The similar question asked before has not addressed some perspectives related to the issue.

In the ANSI C book by Kernighan and Ritchie, they say that the following are equivalent

  • a[i]
  • *(a+i)

I don't see how this can be true for elements that occupy more than one address space, e.g. structs.

Please explain? Edit: Thank you for all answers, but I don't quite understand it. It would seem I am suffering the same confusion as @CucumisSativus from his answer and comments to it.

Say sizeof(*a) is 3. If for some reason I wanted to access the middle byte of the first element in a, I had thought this is how I would do it: *(a+1).

Say the address of a is 10, and the sizeof each element is 20. And say we want to get the pointer to the second element. As I see it, we could do this: p = (10 + 20). I thought this would be equivalent to &a[1].

I'm having real trouble explaining what I don't understand!!

Jodes
  • 14,118
  • 26
  • 97
  • 156

5 Answers5

6

Pointer arithmetic is treated differently than regular integer arithmetic in C. Adding an integer i to a pointer p advances the memory address by i * sizeof(*p), i.e., by i times the size of the type being pointed to.

As a potentially interesting, but practically useless, sidenote: due to the definition of p[i] as *(p+i), the expression i[p] is also equivalent to the same…

Arkku
  • 41,011
  • 10
  • 62
  • 84
3

The + operator is not meant to be the next element in the address space.

The increment is defined by the size of the data type involved. Thus, a + 1 will refer to the next int if a is a pointer to an integer, and will refer to the next struct if a is a pointer to a struct.

axiom
  • 8,765
  • 3
  • 36
  • 38
  • *`not meant to be the next element in the address space.`* ?? It is it start pointing to next element of same type of pointer. – Grijesh Chauhan Feb 25 '14 at 11:37
  • @GrijeshChauhan True. By address space, I meant the word length of the architecture, which is what OP had in mind I reckon. – axiom Feb 25 '14 at 13:09
1

Lets say we have an Integer pointer and a Character pointer as follows

int *a; char *b;

Now assume that a is stored at location 10000 and b is stored at location 20000

So by doing the following operations

*(a+1) : It will return the value contained in address 10004 i.e. (10000+4)
*(b+1) : It will return the value contained in address 20001 i.e. (20000+1)

Reason:

Pointer addition is different from regular arithmetic addition. If you add 1 to an integer pointer it advances the pointer to a location by the size of the integer. So in this case it advances the pointer to 10004. Since character is only 1 byte long it advances the pointer by 1 byte.

user3213851
  • 1,068
  • 2
  • 12
  • 24
0

a+i is translated to something like this in pseudo code

  *(a+i*sizeof(variableType))
CucumisSativus
  • 310
  • 3
  • 11
  • 4
    No, typing `*(a+i)` into the code is equivalent to `a[i]` – if you type `*(a+i*sizeof(*a))` instead you will overshoot unless `sizeof(*a)` is 1. – Arkku Feb 25 '14 at 11:35
  • @Arkku right, what i have written is more like pseudo code than pure c. But you are right, i didnt make myself clear – CucumisSativus Feb 25 '14 at 11:43
  • 2
    The problem with your code is that it is valid C. If you write pseudocode, then state it clearly in the answer or use an unambiguous (totally unrelated) syntax. – Stefano Sanfilippo Feb 25 '14 at 11:54
0

I read more of K&R and found the missing pieces to the puzzle, allowing me to rationalise what's happening. (Whether I'm correct or not is open to debate!)

From what I gather, the following is simply invalid:

p = (10 + 20)
  • Given that, to quote: "Pointers and integers are not interchangeable. Zero is the only exception."
  • I interpret this to mean that *(a+i) is not performing straight forward integer arithmetic.
  • I believe this behaviour is determined by the existence of a pointer in the expression.

And to quote K&R again, and other answers provided to my question, the exact behaviour of arithmetic of arithmetic involving:

  1. one pointer with
  2. one or more integers

for (p + n) is defined like so: "n is scaled according to the size of the objects p points to, which is determined by the declaration of p".

I realised what caused me to be so confused: I have in the past been able to use printf() to output the actual address value of a pointer. I believe this is "undefined behaviour" which the compiler I was using happened to handle by treating the pointer as an integer.

Similarly, given the above two numbered bullet points, and the definition that uses them, I gather that adding two pointers together (of the same type) results in undefined behaviour, and more certainly, adding two pointers of different types.

To get the nth byte of an integer, see this question.

K&R later adds that the following are legal pointer operations:

  • Assigning one pointer to another (of the same type)
  • Adding or subtracting a pointer and an integer
  • Subtracting one pointer from another (to the same array)
  • Comparing pointers (to the same array)
  • Assigning / comparing to 0

All other pointer arithmetic is illegal.

Community
  • 1
  • 1
Jodes
  • 14,118
  • 26
  • 97
  • 156
  • "n is scaled according to the size of the objects p points to, which is determined by the declaration of p". That's precisely what I and Arrku said. – axiom Feb 26 '14 at 10:55
  • Yes, as I said in my answer, " to quote K&R again, and other answers provided to my question" so I acknowledged your responses. What it needed for me to understand was the other quote from K&R, "pointers and integers are not interchangeable". I still gave your answers +1 – Jodes Feb 26 '14 at 11:37