tags:

views:

77

answers:

3

I'm very new to dealing with pointers, and my C knowledge is fairly small. I'm trying to understand pointers. I wrote the following code to print a list of variables (a to f) like so:

0
1
2
3
4
5

I wrote the following code to do this:

#include <stdio.h>
int main(){
  int a,b,c,d,e,f;
  int *p;
  int i;
  a = b = c = d = f = 0;
  p = &a;
  for (i = 0; i < 5; i++){
    *p += i;
    printf("%d\n", *p);
    p++;
  }
  return 0;
}

The idea was it works through the variables and increments each by an ever-increasing number (i). I am assuming that as you initialize the variables at the same time, they'd be placed next to each other in memory. However, I get the following output:

0
1
2
3
-1218283607

If I change the for loop to only go from 0 to 3 (i < 4), it works fine, printer 0 1 2 and 3. But when I wish to print the variable f as well, it doesn't seem to set it.

As I said, I'm very new to pointers so I've probably overlooked something silly, but I've been looking through my code over and over, trying to work it out.

Thanks in advance.

+9  A: 

There is no guarantee that a, b, c, d, e and f will be adjacent in memory. If you want that sort of guarantee you need to use an array.

#include <stdio.h>
int main() {
    int a[6];
    int *p;
    int i;
    a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = 0;
    p = &a[0];
    for (i = 0; i < 6; i++){
        *p += i;
        p++;
    }
    for(i = 0; i < 6; i++) {
        printf("%d\n", a[i]);
    }
    return 0;
}

Here int a[6] is declaring an array named a that can hold six integers. These six integers can obtained via a[0], a[1], a[2], a[3], a[4] and a[5]. You are guaranteed that a[0], a[1], a[2], a[3], a[4] and a[5] are layed out contiguously in memory. Thus the line

p = &a[0];

sets p to the address of the first element. Each increment of this pointer moves us forward one position in the array.

The second for loop shows that first for loops correctly sets a[i] to i for i in {0, 1, 2, 3, 4, 5}. If you run this program you will see

0
1
2
3 
4
5

on the console.

Jason
+3  A: 

You forgot to initialize e. But yes, use a packed array.

Ignacio Vazquez-Abrams
+1  A: 

It isn't safe to assume that stack variables are arranged in memory in any particular order.

You need to use an array, a struct or possibly a union to gurantee the ordering of your ints.

union {
   int ary[6];
   struct {
      int a;
      int b;
      int c;
      int d;
      int e;
      int f;
      } s;
   } u = {0};

  p = &u.s.a;
  for (i = 0; i < 5; i++){
    *p += i;
    printf("%d\n", *p);
    p++;
  }
John Knoeller
Even in the code above, there is nothing stopping a compiler from inserting padding between `a` and `b`, and `b` and `c`, and, ....
Alok
Compilers don't insert padding arbitrarily.
John Knoeller
@John Knoeller: Of course not, but that doesn't invalidate @Alok's comment.
Jason
@John: it's about what's allowed by the standard. One could argue that the most logical thing for a compiler to do is to allocate storage for OP's `a`, `b`, ..., `f` sequentially, but of course, that's not required either.
Alok
I don't buy that. Compilers may be _allowed_ to put spaces in there, but in practice, they can only do that if they are willing to break a lot of existing code for no good reason. In fact, what actual compilers do is go beyond the spec in providing syntax for programmers to be _explicit_ in how they want structures to be packed - and choosing backward compatible defaults otherwise.
John Knoeller