Reputation: 861
I wonder what defines if the start of an memory object is at lower or higher addresses than the end of an object. For example:
char buffer[10];
char* p = &buffer[0];
printf("%p\n",p); //0x7fff064a6276
p = &buffer[9];
printf("%p\n",p); //0x7fff064a627f
In this example the start of object is at a lower address than the end. Even though the stack grows towards lower addresses.
Why does the layout goes the reverse direction of the stack growth?
What defines this direction? Language? OS? Compiler? CPU architecture? ...
Is it always the case that the end of the object is at a higher address than the beginning?
Upvotes: 0
Views: 96
Reputation: 754790
One part of the standard that is relevant is in §6.3.2.3 Pointers (under §6.3 Conversions):
¶7 … When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.
Another relevant portion is §6.7.2.1 Structure and union specifiers:
¶15 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
The definition of addition (and subtraction) is partly relevant (§6.5.6 Additive operators):
¶8 When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. In other words, if the expression
P
points to thei
-th element of an array object, the expressions(P)+N
(equivalently,N+(P)
) and(P)-N
(whereN
has the valuen
) point to, respectively, thei+n
-th andi−n
-th elements of the array object, provided they exist. Moreover, if the expressionP
points to the last element of an array object, the expression(P)+1
points one past the last element of the array object, and if the expressionQ
points one past the last element of an array object, the expression(Q)-1
points to the last element of the array object. 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. If the result points one past the last element of the array object, it shall not be used as the operand of a unary*
operator that is evaluated.
¶9 is a similar paragraph defining the behaviour of subtraction.
And then there's §6.5.2.1 Array subscripting:
¶2 A postfix expression followed by an expression in square brackets
[]
is a subscripted designation of an element of an array object. The definition of the subscript operator[]
is thatE1[E2]
is identical to(*((E1)+(E2)))
. Because of the conversion rules that apply to the binary+
operator, ifE1
is an array object (equivalently, a pointer to the initial element of an array object) andE2
is an integer,E1[E2]
designates theE2
-th element ofE1
(counting from zero).
From these, you know that the address of an object converted to a char *
must point to the lowest byte address holding the object. In practice, this means that the 'object pointer' address of the object also points to the lowest address. The rule in no way enforces that the data in an int
type must be little-endian or big-endian; both are valid.
You also know that the first element in a structure is at a lower address within the structure than later elements.
Upvotes: 2