0

Ok, so on a test I had this question asked:

int* ptrA;    // assigned memory address 100
int a = 1;    // assigned memory address 600
ptrA = &a;

What is the memory address of ptrA + 2?

I thought it was 606 (int is 4 bytes + the address of a which is 600 + 2 = 606 but apparently the answer was 608, what am I missing to make this true?

Howdy_McGee
  • 10,422
  • 29
  • 111
  • 186
  • 6
    If that's how the test question was phrased, the test sucks. – John Carter Oct 10 '12 at 04:42
  • 3
    I doubt very much that this is what was actually asked on the test ... at the very least there would be `PtrA = &a` somewhere. – Jim Balter Oct 10 '12 at 04:46
  • @Jim: unless the question was deliberately checking that such an error was noticed by the student.... – Tony Delroy Oct 10 '12 at 05:00
  • @TonyD That's silly, and would make the test question far worse than it is already. See the OP's edit. – Jim Balter Oct 10 '12 at 05:01
  • The answer should be 100 + (2*sizeof(int)). God knows where 608 is coming from if there is `no PtrA = &a` statement – auny Oct 10 '12 at 05:02
  • @JimBalter: if you never had silly questions on your test - deliberately or otherwise - you must have had a much better education than anyone I know.... If the OP's edit subsequently says this wasn't the case in this specific question, it hardly invalidates my having raised the possibility beforehand. – Tony Delroy Oct 10 '12 at 11:35
  • @TonyD My education was adequate to provide an accurate inference of what this test question is testing for. – Jim Balter Oct 10 '12 at 17:51
  • @JimBalter: congratulations mate... you're my new hero. – Tony Delroy Oct 11 '12 at 01:01

6 Answers6

5

It's undefined behavior, the expression PtrA + 2 is illegal. You can only do pointer arithmetic on pointers you own and can't add or substract to/from pointers outside the range of an array you own or one beyond the range.

We can still analyze this however (although useless, because of UB). You assume the address of a is 600 + 2, but it's not, since probably sizeof(int*) is also 4, so this becomes 600 + 4. So you get 600 + 4 + 4 = 608.

Jim Balter
  • 16,163
  • 3
  • 43
  • 66
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I'm a little confused how +2 turned into +4. So for example - if the question was `ptrA + 10` would it be 600+4+10 = 614? – Howdy_McGee Oct 10 '12 at 04:44
  • 2
    @Howdy_McGee This may feel counterintuitive, but adding 2 to an `int*` moves the address _two ints_, not _two bytes_. Because an int is 4 bytes wide, you're actually adding 8 bytes to the original address. – Jeff Bowman Oct 10 '12 at 04:47
  • UB aside, are there any real-world architectures where pointer arithmetic with invalid pointers doesn't work? (assuming you never dereference the invalid pointers, of course) – Jeremy Friesner Oct 10 '12 at 04:48
  • The `600 + 4` part is nonsense ... that is the value of PtrA + 1, which isn't mentioned anywhere. – Jim Balter Oct 10 '12 at 04:48
  • Just think of it as `600 + (2 * sizeof(int))` instead of just `600 + 2`. – Geoff Montee Oct 10 '12 at 04:48
  • 1
    hey @Howdy_McGee: for your query it will be 600 + (4)*10 = 640 . See my Comment Below .. Thanks – Neelam Verma Oct 10 '12 at 04:50
  • -1: Pointer arithmetic is not an undefined behavior. It is fully legal. Accessing something using pointer of unclear origin CAN AND MOST LIKELY WILL cause an undefined behavior. But dereferencing pointer is not the same to the machinery of the pointer arithmetic itself. – Kirill Kobelev Oct 10 '12 at 04:52
  • 2
    @KirillKobelev RTFStandard ... you're wrong. Only the address of the element **1** beyond the end of an object can be taken ... going beyond that is UB. – Jim Balter Oct 10 '12 at 04:55
  • @Krill, that's not what the standard says. It says the calculation _itself_ is undefined (C99 6.5.6 (Additive operators) /8 on adding an arithmetic value to a pointer). Nothing about having to dereference to get UB. – paxdiablo Oct 10 '12 at 04:56
  • Found an answer to my question above (and perhaps a good example for @Kirill too) here: http://stackoverflow.com/a/10474204/131930 – Jeremy Friesner Oct 10 '12 at 04:57
  • @KirillKobelev You're wrong, see 5.7 Additive operators §5. `If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.` – fredoverflow Oct 10 '12 at 04:58
  • Will @KirillKobelev be a good SO citizen, admit error, and remove that bogus downvote? – Jim Balter Oct 10 '12 at 05:02
  • @Jim, There is not a lot of space in the comment, nevertheless I will try. `int *f(int *p, int inx) { return(p+inx); }` Is this a legitimate function? Can it be used in the context `int b[10]; int *pp = f(b, 3);`? If yes, how can compiler compile the function itself? Please, answer (as a good SO citizen). – Kirill Kobelev Oct 10 '12 at 05:07
  • @KirillKobelev More than one person has quoted the relevant part of the standard to you. According to the standard, `f(b, 3)` is fine, as is `f(b, 10)`, but `f(b, 11)` is non-conforming. Now remove that bogus downvote. – Jim Balter Oct 10 '12 at 05:11
  • @jim, please, be a good SO citizen. Answer my first question. What about the function itself? Is it conformant? – Kirill Kobelev Oct 10 '12 at 05:13
  • @KirillKobelev I AM being a good citizen. The function is conformant and no one ever said it isn't. But that doesn't mean that *every invocation* is fine ... UB is about *behavior*. `ptrA+N` is fine too (given that ptrA is &a) ... if N is 0 or 1; but it isn't fine if N is 2. Now *be a good citizen* and remove your bogus downvote. Or don't be a good citizen; your choice. – Jim Balter Oct 10 '12 at 05:15
  • I can remove, not problem. The vote is locked. Somebody needs to edit the answer. – Kirill Kobelev Oct 10 '12 at 05:19
  • @KirillKobelev I've made a small edit. BTW, I already implicitly answered your first question when I said that `f(b, 3)` is fine. – Jim Balter Oct 10 '12 at 05:20
  • @Jim, thanks. Lets forget about call places and focus on the function. As you sad it is fine. Please, explain me how `p+inx` differ from `ptrA+2`? Both `p` and `ptrA` have the same type. When compiling `+` compiler cannot make and is not making any assumptions about the value of the pointer. This is my point. And it is correct. – Kirill Kobelev Oct 10 '12 at 05:23
  • @KirillKobelev it's contextual. It's like asking "is `*ptr` legal. Sure, it's legal if `ptr = new int`, but illegal if `ptr = NULL`. Right? – Luchian Grigore Oct 10 '12 at 06:14
  • Please move extended discussions to [chat]. Thanks :) – Tim Post Oct 10 '12 at 06:32
  • No guys. You are not right. Meaning of the bigger part of the program is not the same the the meaning of a small part or one statement. I was making right statements about pointer arithmetic. Not about anything else in a bigger context. You failed to refute my statements. – Kirill Kobelev Oct 10 '12 at 07:13
3

Actually Arithmetic operations on Pointers are different. They Increase depends on the size of data type so if one address is given say x and u have to ask for x+ 2.. (given x is a integer Pointer) then ..

x+ 2 means ---- x + (sizeof(int))*2

if x is given as char pointer then

x+2 means ---- x + (sizeof(char))*2

Thanks.

Neelam Verma
  • 3,232
  • 1
  • 22
  • 33
  • y are u saying that it would be sizeof(int*) or sizeof(char*). Both these sizes are the same. It is sizeof(int) or sizeof(char) – auny Oct 10 '12 at 05:00
1

In C, x + y where x is a pointer is equivalent to &x[y]. Suppose that you had

int abc[3] = {1,2,3}; 
int* ptr = &abc[0];

&ptr[2] (ptr + 2) is the address of the 3, which is clearly 8 more than the address of the 1.

Jim Balter
  • 16,163
  • 3
  • 43
  • 66
1
int* PtrA;    // assigned memory address 100
int a = 1;    // assigned memory address 600

What is the memory address of ptrA + 2? 

The question is ambiguous.

If the question is "What is (the memory address of ptrA) + 2?", then you've said ptrA is at memory address 100 (ignoring PtrA != ptrA), and adding 2 to a pointer in C and C++ increments things in multiples of the pointed-to type's size, so if int is 32 bits then the final result is 100 + 2 * 4 = 108.

If the question is "What is the memory address of (ptrA + 2)?", meaning the result of adding the value in the ptrA variable and 2, then that is undefined as no initialisation of ptrA is shown and it's undefined behaviour to try to read from uninitialised memory.

Your expectations and the supposed answer suggest the intended code had...

ptrA = &a;

...sometime before the ptrA + 2 was to be evaluated. If that were true, then the answer would be 600 + 2 * sizeof(int), which is very likely to be 608.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • +1 for the clean descrptition of the ambiguity in the question, that reveals the illiteracy of the author of the test. The purpose of tests should be to prove knowledge, not to issue traps asking thing impossible to be understood to cheat about wrong answers (especially where any answer can be true of false by reverting the meaning of the questions!) – Emilio Garavaglia Oct 10 '12 at 06:25
0

In C/C++ the pointer arithmetic uses the size of the object that the pointer is pointing at. Ex:

int* PtrA = (int*)600;

The value of PtrA+2 will be 608 provided that the size of integer is 4.

Standard allows to do pointer arithmetic only inside arrays or "right after the array". This means that certain care should be taken.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
0

I think, it is not true that address will always be more. It can be less as well. What is sure is that say ptr is pointer to base address of an array a of integers, then ptr+2 will point to 3rd element of the array. So if base address of array is 600, then address can be 600+2*(sizeofIint)) or it may be 600-2*sizeof(int); But in anycase, it will point to 3rd element of that array. So, I believe that even in cases of arrays, we should not rely on direct addresses. and should not make any assumptions about whether ptr+2 will point to 608 or something else.

Thanks & Regards, Saurabh