One of the examples of undefined behavior from the C standard reads (J.2):
— An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6)
If the declaration is changed from int a[4][5]
to unsigned char a[4][5]
, does accessing a[1][7]
still result in undefined behavior? My opinion is that it does not, but I have heard from others who disagree, and I'd like to see what some other would-be experts on SO think.
My reasoning:
By the usual interpretation of 6.2.6.1 paragraph 4, and 6.5 paragraph 7, the representation of the object
a
issizeof (unsigned char [4][5])*CHAR_BIT
bits and can be accessed as an array of typeunsigned char [20]
overlapped with the object.a[1]
has typeunsigned char [5]
as an lvalue, but used in an expression (as an operand to the[]
operator, or equivalently as an operand to the+
operator in*(a[1]+7)
), it decays to a pointer of typeunsigned char *
.The value of
a[1]
is also a pointer to a byte of the "representation" ofa
in the formunsigned char [20]
. Interpreted in this way, adding 7 toa[1]
is valid.
unsigned char
example doesn't also apply to theint
example described in the standard? – Thirtyoneint
or some other type that overlaps it results in undefined behavior. The only types which can be used this way are the character types (char
,signed char
, andunsigned char
). – Segura