1
int i = 9;
int *j = &i;
int* l = j + 1; 
int **a=&j;
int **b=&l;
printf("%u\n",a);
printf("%u\n",b);
printf("%d\n",a-b);

Output:6422208 6422204 1. What is 1 indicating to?

  • 2
    note, while printing a pointer, use `%p` and cast the argument to `void*` – Sourav Ghosh Jan 22 '21 at 07:06
  • And to print the type `ptrdiff_t` (which is the type of the result of pointer subtraction) use `%td`. See e.g. [this `printf` reference](https://en.cppreference.com/w/c/io/fprintf). – Some programmer dude Jan 22 '21 at 07:07
  • 2
    And IIRC it's only allowed to subtract pointers if they both point to the same "array", that the pointers are really "related". Since `&j` and `&l` aren't "related" you can't really subtract them and expect a sensible result. – Some programmer dude Jan 22 '21 at 07:09

2 Answers2

1

a contains the adress of the variable j (which contains itself the adress of variable i)

b is the adress of l.

Then the first two printf show you the adresses where variables j and l have been allocated to.

In your example j and l are contiguous in memory (I assume int is 32 bits on your architecture). It is just by luck, they could have been located far away from each other.

Finally, when you substract 2 pointers as in the last printf, you are doing arithmetic on pointers.

Incrementing a pointer adds to the adress the length of the type pointed to. For example if you print the values of variables j and l (not their adresses) you would find a difference of 4 between both adresses.

Similarly, the substraction of both adresses equals 4 which represent a difference of 1 in terms of pointer arithmetic for 32 bits architecture. That's why it prints the value 1.

However keep in mind that pointer arithmetic can be tricky. About substraction the C99 Standard states that:

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

So here I think you are allowed to substract a and b but this is not something you want to do in a real code.

Guillaume Petitjean
  • 2,408
  • 1
  • 21
  • 47
0

Your code is unclean in many ways, see the comments. With that code doing experiments like the one you try to do will not give reliable results.

However lets assume that you have used appropriate code to output the difference of two addresses of pointers to int, of two variable int* j; int* l;.

&j is the address of the variable j, you can store it in a int** a;, same for int** b=&l;.

The value of the difference a-b now is only the difference of the addresses.
For that address difference, this line of your code is irrelevant. int* l = j + 1;, it only affects the value of what is pointed to by &l, i.e. not the address &l.

The value 1 cannot be explained reliably, because there is some freedom of implementation involved. But in many cases, this int *j; int *l; will result in j ending up immediatly "after" l in memory, i.e. at the next highest address. Because of pointer arithmetic this result in &j == (&l)+1. At this point the value of 1 for &j-&l is obvious.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • "But in many cases, this int *j; int *l; will result in j ending up immediatly "after" l in memory, i.e. at the next highest address". Worth adding it is due to the fact variables are put on the stack in most cases and the stack is "descending". – Guillaume Petitjean Jan 22 '21 at 07:58
  • @GuillaumePetitjean I am not sure that all of the shown code is inside a function, because it is not really a MRE. Also the standard does not define what a stack is. I tried to phrase around those (very plausible) assumptions and am happier without making them. – Yunnosch Jan 22 '21 at 08:01
  • You're entirely right. Should have written "it might due to the fact..." – Guillaume Petitjean Jan 22 '21 at 08:02
  • In my experience the order is also observed for most non-stack (e.g. global) variables. @GuillaumePetitjean – Yunnosch Jan 22 '21 at 08:09
  • I don't agree. If they were global variables, `l` would typically be located after `j` in memory , and not before. Or in other words, located in the same order than declaration. of course as you pointed out, it depends on many things, compiler, architecture, ABI, etc... – Guillaume Petitjean Jan 22 '21 at 08:56
  • @GuillaumePetitjean I might remember incorrectly (or remember weird edge cases). Thanks for pointing out. I will keep in mind and verify/falsify my memory. Luckily I phrased carefully. – Yunnosch Jan 22 '21 at 08:59