Weird Pointer Outcome: Analyzing Activation Record 6

  • Thread starter Thread starter STEMucator
  • Start date Start date
  • Tags Tags
    Weird
AI Thread Summary
The discussion centers on the behavior of pointer arithmetic in C, particularly regarding the pointer variable `r` in the provided code. When `r++` is executed, it points to the memory address of `x`, which is due to how local variables are typically allocated on the stack. The conversation highlights that pointer arithmetic is scaled by the type of object being pointed to, leading to potential confusion when incrementing pointers that do not reference arrays. Participants note that while pointer arithmetic can be useful in low-level programming, it can also lead to unpredictable behavior if misused. The consensus emphasizes the importance of understanding memory allocation and pointer behavior in C programming.
STEMucator
Homework Helper
Messages
2,076
Reaction score
140

Homework Statement



Not homework, but I don't really know where else to put this.

Below is some code and it's relevant output, but the output is what I'm concerned about.

Homework Equations

The Attempt at a Solution



Code:
#include <stdio.h>
#include <stdlib.h>

void foo(int a, int b) {
  int r = a+b;
  a += 2;
  printf("(AR1) r = %d, a = %d \n", r, a);
}

void foo2(int *a, int *b){
  *a = (*a)*2;
  b = a;
  printf("(AR2) *a = %d, *b = %d \n", *a, *b);
}

int main() {
  int x = 5, y = 2;
  int *p = &x, *r = &y;
  printf("(AR3) x = %d, y = %d, *p = %d, *r = %d \n", x, y, *p, *r);
   
  foo(x,y);
  printf("(AR4) x = %d, y = %d, *p = %d, *r = %d \n", x, y, *p, *r);

  foo2(p,r);
  printf("(AR5) x = %d, y = %d, *p = %d, *r = %d \n", x, y, *p, *r);

  r++;
  printf("(AR6) x = %d, y = %d, *p = %d, *r = %d \n", x, y, *p, *r);
   
  return 0;
}

This produces the following output:

Code:
(AR3) x = 5, y = 2, *p = 5, *r = 2
(AR1) r = 7, a = 7
(AR4) x = 5, y = 2, *p = 5, *r = 2
(AR2) *a = 10, *b = 10
(AR5) x = 10, y = 2, *p = 10, *r = 2
(AR6) x = 10, y = 2, *p = 10, *r = 10

Activation record 6 is of some interest. For some reason, when ##r++## is read, the pointer ##r## decides to point to the same value ##p## is pointing to (which is ##x = 10##).

Why does this happen?

Executing ##r++## again interestingly made ##r## point to zero.
 
Physics news on Phys.org
'r' is of type 'pointer to int', i.e. it stores a memory address. When you execute 'r++', you're doing pointer arithmetic - you're increasing the memory address stored in 'r' by sizeof(int). That so happens to be the address of 'x'.
 
As a sidenote: If you want to know why incrementing 'r' makes it point to 'x', you should look up how variables are allocated on the stack and how that's typically organized in memory for your platform.
 
There's a phrase that's useful to memorize:
Pointer arithmetic is scaled by the type of object that is pointed to.
Assuming that ptr is a pointer variable, then the expressions ptr + 1 and ptr++ will have different values depending on how ptr is declared.

If ptr is of type char *, then ptr + 1 and ptr++ both contain the address of the next byte in memory (assuming a char is a single byte).
If ptr is of type int *, then ptr + 1 and ptr++ both contain the address of the next int in memory, which likely will be four bytes higher in memory, assuming an int is four bytes.

Pointer decementing and subtracting an int value from a pointer variable work in a similar way.
 
Mark44 said:
If ptr is of type int *, then ptr + 1 and ptr++ both contain the address of the next int in memory, which likely will be four bytes higher in memory, assuming an int is four bytes.

Thank you for making that apparent. So if I have n ints (not in an array) then ptr++ will point to the next integer (likely sizeof(int) higher in memory). I found that weird and counter-intuitive.

Usually we use a pointer to the address of the zero'ith element in an array (&arr[0] == arr). Makes more sense to do it that way anyway.
 
Zondrina said:
So if I have n ints (not in an array) then ptr++ will point to the next integer (likely sizeof(int) higher in memory).
You have no guarantee of this. Arrays in C are contiguous in the (virtual) memory space of your application, but variables with local scope, like your 'x', can be allocated however your compiler sees fit. 'ptr++' might point to garbage or perhaps even a virtual memory page that has no physical mapping yet, which will you give you a run-time error when you try to access it.

With that said, it's typical for most C compilers to allocate local variables, in order of appearance, in a LIFO structure in low memory (the stack), which grows "downwards" in memory from high to low memory addresses. Assuming a 4-byte int, the stack frame for 'main' in your application might look like this:

Address, Symbol
00000000, 'r'
00000004, 'p'
00000008, 'y'
0000000C, 'x'

So 'r' and 'r++' contain 0x8 and 0xC, respectively.
 
milesyoung said:
You have no guarantee of this. Arrays in C are contiguous in the (virtual) memory space of your application, but variables with local scope, like your 'x', can be allocated however your compiler sees fit. 'ptr++' might point to garbage or perhaps even a virtual memory page that has no physical mapping yet, which will you give you a run-time error when you try to access it.

With that said, it's typical for most C compilers to allocate local variables, in order of appearance, in a LIFO structure in low memory (the stack), which grows "downwards" in memory from high to low memory addresses. Assuming a 4-byte int, the stack frame for 'main' in your application might look like this:

Address, Symbol
00000000, 'r'
00000004, 'p'
00000008, 'y'
0000000C, 'x'

So 'r' and 'r++' contain 0x8 and 0xC, respectively.

I wonder why C99 does this; p++ could point you to the next address of a local variable, or it could go boom and point essentially nowhere. Pointer arithmetic on anything except array names seems to be tacky.
 
Zondrina said:
I wonder why C99 does this; p++ could point you to the next address of a local variable, or it could go boom and point essentially nowhere. Pointer arithmetic on anything except array names seems to be tacky.

It's 'tacky' when abused but when used in the right context (operating systems,embedded design,etc..) it's elegant.
http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html
 
Zondrina said:
I wonder why C99 does this; p++ could point you to the next address of a local variable, or it could go boom and point essentially nowhere. Pointer arithmetic on anything except array names seems to be tacky.
I would agree with nsaspook here. When working "close to the metal" with resource-limited systems, it's very useful to be able to index directly into the address space.

However, it's certainly no secret that C allows you ample freedom in setting up a shot to the foot.
 
  • #10
From the perspective of a developer who is writing applications, there's not much reason for you to use pointer arithmetic (such as incrementing a pointer) for memory that doesn't belong to an array.

From the perspective of someone writing operating system code, which was main reason C was created, there are good reasons, as nsaspook and milesyoung have already mentioned.
 

Similar threads

Replies
3
Views
1K
Replies
3
Views
1K
Replies
3
Views
2K
Replies
2
Views
2K
Replies
6
Views
2K
Replies
5
Views
3K
Back
Top