D
David Hopwood
Wojtek said:Wojtek said:Wojtek Lerch wrote:
What you seem to be saying is that for a region of memory to constitute
an array of four ints, it doesn't have to be declared with a type that
involves an array of four ints, or designated by an lvalue with such a
type, but nevertheless it must be declared with some aggregate type
ultimately consisting of four ints and no padding bytes between them.
Yes. This view is based on the definition of "array type" as being the
type of any contiguous nonempty sequence of objects of the element type.
In order
Not just *any* contiguous sequence. A struct type that consists of four
ints and turns out to have no padding bytes is not an array type. It's a
struct type.
Yes, but a region that holds an object declared using such a struct type
can also be accessed as an object of the array type int[4]. All that is
required for this is that the four ints be contiguous.
If, OTOH, we did not have any way to infer that the region can hold four
ints, then we couldn't access it as an object of type int[4].
But when we're not accessing it as an object of type int[4], it's not an
object of tye int[4]. "When an object is said to have a particular type,
the type is specified by the lvalue used to designate the object"
(6.3.2.1p1).
No. Objects are typed; memory regions aren't.
No. Objects are regions of memory; lvalues that designate objects are
typed. "When an object is said to have a particular type, the type is
specified by the lvalue used to designate the object."
That isn't actually consistent with how the standard uses the term "object".
If you search for "object" you'll see that in most cases the usage depends
on objects (and *not* just lvalue expressions) having a type. For example:
# 3.2
# alignment
# requirement that objects of a particular type be located [...]
# 3.5
# bit
# unit of data storage in the execution environment large enough to
# hold an object that may have one of two values
[memory regions cannot have values; objects can only have values because
they have a type]
# 3.7.3
# wide character
# bit representation that fits in an object of type wchar_t [...]
# 3.15
# parameter [...]
# object [...] that acquires a value on entry to the function
[again, objects can only have values because they have a type]
# 5.1.2 Execution environments
# [...] All objects with static storage duration shall be /intialized/ (set
# to their initial values) before program startup. [...]
[there is no lvalue expression involved in this case]
etc., etc.
Even more accurately, the effective type of an allocated object can be
*changed* to any given type by using an lvalue of that type to store a value
in the object.
This is not a more accurate statement of the same thing; it's an entirely
different semantics. C implementations actually implement what I said.