neo
neo

Reputation: 1404

Why the output of this 'C' code is like this?

I have following C code:

#include<stdio.h>
#include<stdlib.h>
int main() {

int a[4] = {1,2,3,4};

int b[4] = {1,2,3,4};

int n = &b[3] - &a[2];

printf("%d\n", n);

return 0;
}

Why the value of n is -3? I don't have a pure explanation for that. How can the difference between the addresses of the variables be a -3? And why it is exactly -3?

Upvotes: 1

Views: 708

Answers (3)

Eric Postpischil
Eric Postpischil

Reputation: 222942

While the C standard does not define the behavior when you subtract pointers to elements in different arrays, what seems to have happened is that your compiler put b in memory just before (at a lower address than) a. Thus, the memory layout looked like:

+------+------+------+------+------+------+------+------+
| b[0] | b[1] | b[2] | b[3] | a[0] | a[1] | a[2] | a[3] |
+------+------+------+------+------+------+------+------+

Given this memory layout, &a[2] - &b[3] is +3 because a[2] is three elements later in memory than b[3]. Then &b[3] - &a[2] is -3 because b[3] is three elements earlier in memory than a[2]. (Note that simple pointer arithmetic like this that does not conform to the C standard can break because the compiler may perform various optimizations or because address arithmetic is complicated on some architectures. The C standard does not just not define the result of the subtraction; it does not define the behavior of the program at all once an undefined subtraction is performed.)

Many C implementations put objects on a stack (if they have automatic storage duration, rather than static, allocated, or thread), and it is common for the stack to start at a high memory address and grow toward lower addresses. So, if the compiler is simply allocating space for objects in the order you declare them (this is not to be expected generally; there are a number of reasons to do fancier things), then it effectively would put a on the stack first, then decrease the stack pointer, and then put b on the stack, so b ends up at a lower address than a.

Incidentally, the result of subtracting two pointers has size ptrdiff_t, which is not necessarily int, so it ought to be printed with printf("%td\n", n); rather than %d, and n should be declared with ptrdiff_t n; rather than int n;. The ptrdiff_t type is defined in the <stddef.h> header.

Upvotes: 14

Foran
Foran

Reputation: 192

With C calling convention (on x86) local variables are pushed onto the local stack and as a result are adjacent in memory.

In this case the two arrays are relatively adjacent in memory. (The exact value can be effected by things like byte/word/qword alignment)

The end result you'll get a consistent value, that can be predicable given your build environment/options.

Upvotes: -3

Bathsheba
Bathsheba

Reputation: 234715

The behaviour of the code is undefined.

Pointer arithmetic, including the subtraction of two pointers, is only valid for pointers to elements within the same array. (For this purpose you can set a pointer to one past the end of an array, and an object counts as an array with one element.)

Upvotes: 4

Related Questions