Access an array from the end in C? - c

I recently noticed that in C, there is an important difference between array and &array for the following declaration:
char array[] = {4, 8, 15, 16, 23, 42};
The former is a pointer to a char while the latter is a pointer to an array of 6 chars. Also it is notable that the writing a[b] is a syntactic sugar for *(a + b). Indeed, you could write 2[array] and it works perfectly according to the standard.
So we could take advantage of this information to write this:
char last_element = (&array)[1][-1];
&array has a size of 6 chars so (&array)[1]) is a pointer to chars located right after the array. By looking at [-1] I am therefore accessing the last element.
With this I could for example swap the entire array :
void swap(char *a, char *b) { *a ^= *b; *b ^= *a; *a ^= *b; }
int main() {
char u[] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < sizeof(u) / 2; i++)
swap(&u[i], &(&u)[1][-i - 1]);
}
Does this method for accessing an array by the end have flaws?

The C standard does not define the behavior of (&array)[1].
Consider &array + 1. This is defined by the C standard, for two reasons:
When doing pointer arithmetic, the result is defined for results from the first element (with index 0) of an array to one beyond the last element.
When doing pointer arithmetic, a pointer to a single object behaves like a pointer to an array with one element. In this case, &array is a pointer to a single object (that is itself an array, but the pointer arithmetic is for the pointer-to-the-array, not a pointer-to-an-element).
So &array + 1 is defined pointer arithmetic that points just beyond the end of array.
However, by definition of the subscript operator, (&array)[1] is *(&array + 1). While the &array + 1 is defined, applying * to it is not. C 2018 6.5.6 8 explicitly tells us, about result of pointer arithmetic, “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.”
Because of the way most compilers are designed, the code in the question may move data around as you desire. However, this is not a behavior you should rely on. You can obtain a good pointer to just beyond the last element of the array with char *End = array + sizeof array / sizeof *array;. Then you can use End[-1] to refer to the last element, End[-2] to refer to the penultimate element, and so on.

Although the Standard specifies that arrayLvalue[i] means (*((arrayLvalue)+(i))), which would be processed by taking the address of the first element of arrayLvalue, gcc sometimes treats [], when applied to an array-type value or lvalue, as an operator which behaves line an indexed version of .member syntax, yielding a value or lvalue which the compiler will treat as being part of the array type. I don't know if this is ever observable when the array-type operand isn't a member of a struct or union, but the effects are clearly demonstrable in cases where it is, and I know of nothing that would guarantee that similar logic wouldn't be applied to nested arrays.
struct foo {unsigned char x[12]};
int test1(struct foo *p1, struct foo *p2)
{
p1->x[0] = 1;
p2->x[1] = 2;
return p1->x[0];
}
int test2(struct foo *p1, struct foo *p2)
{
char *p;
p1->x[0] = 1;
(&p2->x[0])[1] = 2;
return p1->x[0];
}
The code gcc generates for test1 will always return 1, while the generated code for test2 will return whatever is in p1->x[0]. I am unaware of anything in the Standard or the documentation for gcc that would suggest the two functions should behave differently, nor how one should force a compiler to generate code that would accommodate the case where p1 and p2 happen to identify overlapping parts of an allocated block in the event that should be necessary. Although the optimization used in test1() would be reasonable for the function as written, I know of no documented interpretation of the Standard that would treat that case as UB but define the behavior of the code if it wrote to p2->x[0] instead of p2->x[1].

I would do a for loop where I set i = length of the vector - 1 and each time instead of increasing it, I decrease it until it is greater than 0.
for(int i = vet.length;i>0;i--)

Related

Explanation how pointers and multidimensional arrays work in C

I am trying to understand the following code.
#include <stdio.h>
#include <stdlib.h>
void print2(int (* a)[2]) {
int i, j;
for (i = 0; i < 3; i++ ) {
for (j = 0; j < 2; j++ ) {
printf("%d", a[i][j]);
}
printf("\n");
}
}
void print3(int (* a)[3]) {
int i, j;
for (i = 0; i < 2; i++ ) {
for (j = 0; j < 3; j++ ) {
printf("%d", a[i][j]);
}
printf("\n");
}
}
int main() {
int a[] = { 1, 2, 3, 4, 5, 6 };
print2((int (*)[2]) a);
print3((int (*)[3]) a);
return 0;
}
Running the code returns following output in console:
12
34
56
123
456
My problem is I don't understand where these numbers come from. I have trouble understanding what is actually going on in this code. More specifically, I'm uncertain of what this means:
int( (* a)[2])
I hope someone can explain this code to me, because I really want to understand how pointers and multidimensional arrays work in C.
TL;DR
This code contains incorrect and meaningless hacks. There is not much of value to learn from this code.
Detailed explanation follows.
First of all, this is a plain 1D array that gets printed in different ways.
These lines are strictly speaking bugs:
print2((int (*)[2]) a);
print3((int (*)[3]) a);
In both cases there is an invalid pointer conversion, because a is of type int[6] and a pointer to the array a would have to be int (*)[6]. But the print statements are wrong in another way too, a when used in an expression like this "decays" into a pointer to the first element. So the code is casting from int* to int(*)[2] etc, which is invalid.
These bugs can in theory cause things like misaligned access, trap representations or code getting optimized away. In practice it will very likely "work" on all mainstream computers, even though the code is relying on undefined behavior.
If we ignore that part and assume void print2(int (*a)[2]) gets a valid parameter, then a is a pointer to an array of type int[2].
a[i] is pointer arithmetic on such a type, meaning that each i would correspond to an int[2] and if we had written a++, the pointer would jump forward sizeof(int[2]) in memory (likely 8 bytes).
Therefore the function abuses this pointer arithmetic on a[i] to get array number i, then do [j] on that array to get the item in that array.
If you actually had a 2D array to begin with, then it could make sense to declare the functions as:
void print (size_t x, size_t y, int (*a)[x][y])
Though this would be annoying since we would have to access the array as (*a)[i][j]. Instead we can use a similar trick as in your code:
void print (size_t x, size_t y, int (*a)[x][y])
{
int(*arr)[y] = a[0];
...
arr[i][j] = whatever; // now this syntax is possible
This trick too uses pointer arithmetic on the array pointer arr, then de-references the array pointed at.
Related reading that explains these concepts with examples: Correctly allocating multi-dimensional arrays
void print2(int (*a)[2]) { /*...*/ }
inside the function print2 a is a pointer to arrays of 2 ints
void print3(int (*a)[3]) { /*...*/ }
inside the function print3 a is a pointer to arrays of 3 ints
int a[] = {1, 2, 3, 4, 5, 6};
inside the function main a is an array of 6 ints.
In most contexts (including function call context) a is converted to a pointer to the first element: a value of type "pointer to int".
The types "pointer to int", "pointer to array of 2/3 ints" are not compatible, so calling any of the functions with print2(a) (or print3(a)) forces a diagnostic from the compiler.
But you use a cast to tell the compiler: "do not issue any diagnostic. I know what I'm doing"
print3(a); // type of a (after conversion) and type of argument of print3 are not compatible
// print3((cast)a); // I know what I'm doing
print3((int (*)[3])a); // change type of a to match argument even if it does not make sense
It would be much easier to understand if you break it down and understand things. What if you were to pass the whole array to say a function print4, which iterates over the array and prints the elements? How would you pass the array to such a function.
You can write it something like
print4( (int *) a);
which can be simplified and just written as print4(a);
Now in your case by doing print2((int (*)[2]) a);, you are actually designing a pointer to an array of 2 int elements. So now the a is pointer in array of two elements i.e. every increment to the pointer will increase the offset by 2 ints in the array a
Imagine with the above modeling done, your original array becomes a two dimensional array of 3 rows with 2 elements each. That's how your print2() element iterates over the array a and prints the ints. Imagine a function print2a that works by taking a local pointer to a and increments at each iteration to the point to the next two elements
void print2a(int (* a)[2]) {
int (* tmp)[2] = a;
for( int i = 0; i < 3; i++ ) {
printf("%d%d\n", tmp[0][0], tmp[0][1] );
tmp++;
}
}
The same applies to print3() in which you pass an pointer to array of 3 ints, which is now modeled as a 2-D array of 2 rows with 3 elements in it.
The code seeks to reinterpret the array int a[6] as if it were int a[3][2] or int a[2][3], that is, as if the array of six int in memory were three arrays of two int (in print2) or two arrays of three int (in print3).
While the C standard does not fully define the pointer conversions, this can be expected to work in common C implementations (largely because this sort of pointer conversion is used in existing software, which provides motivation for compilers to support it).
In (int (*)[2]) a, a serves as a pointer to its first element.1 The cast converts this pointer to int to a pointer to an array of two int. This conversion is partially defined C 2018 6.3.2.3 7:
The behavior is undefined if the alignment of a is not suitable for the type int (*)[2]. However, compilers that have stricter alignment for arrays than for their element types are rare, and no practical compiler has a stricter alignment for an array of six int than it does for an array of two or three int, so this will not occur in practice.
When the resulting pointer is converted back to int *, it will compare equal to the original pointer.
The latter property tells us that the resulting pointer contains all the information of the original pointer, since it must contain the information needed to reconstruct the original pointer. It does not tell us that the resulting pointer is actually pointing to the memory where a is.
As noted above, common C implementations allow this. I know that Apple’s versions of GCC and Clang support this reshaping of arrays, although I do not know whether this guarantee was added by Apple or is in the upstream versions.
Given that (int (*)[2]) is passed to print2 as its a, then a[i][j] refers to element j of array i. That is, a points to an array of two int, so a[0] is that array, a[1] is the array of two int that follows it in memory, and a[2] is the array of two int after that. Then a[i][j] is element j of the selected array. In effect, a[i][j] in print2 is a[i*2+j] in main.
Note that no aliasing rules are violated as no arrays are accessed by a[i][j]: a is a pointer, a[i] is an array but is not accessed (it is automatically converted to a pointer, per footnote 1 below), and a[i][j] has type int and accesses an object with effective type int, so C’s aliasing rules in C 2018 6.5 7 are satisfied.
Footnotes
1 This is because when an array is used in an expression, it is automatically converted to a pointer to its first element, except when it is the operand of sizeof, is the operand of unary &, or is a string literal used to initialize an array.

Iterating over a 2D array with a single char pointer

While doing some research on multi-dimensional arrays in C and how they're stored in memory I came across this: "Does C99 guarantee that arrays are contiguous?". The top-voted answer states that "It must also be possible to iterate over the whole array with a (char *)," then provides the following "valid" code:
int a[5][5], i, *pi;
char *pc;
pc = (char *)(&a[0][0]);
for (i = 0; i < 25; i++)
{
pi = (int *)pc;
DoSomething(pi);
pc += sizeof(int);
}
The poster then goes on to say that "Doing the same with an (int *) would be undefined behavior, because, as said, there is no array[25] of int involved."
That line confuses me.
Why does using a char pointer constitute as valid / defined behavior while substituting it with an integer pointer doesn't?
Sorry if the answer to my question should be obvious. :(
The difference between using a char* and an int* is strict aliasing rules: If you access (&a[0][0])[6] (i. e. via an int*), the compiler is free to assumes that the access [6] does not leave the array at a[0]. As such, it is free to assumes that (&a[0][0]) + 6 and a[1] + 1 point to different memory locations, even though they don't, and reorder their accesses accordingly.
The char* is a difference because it is explicitly exempted from strict aliasing rules: You can cast anything to a char* and manipulate its bits through this pointer without invoking undefined behavior.
The standard is very clear that if you have:
int a[5];
int* p = &a[0];
Then
p += 6;
is cause for undefined behavior.
We also know that memory allocated for a 2D array such as
int a[5][5];
must be contiguous. Given that, if we use:
int* p1 = &a[0][0];
int* p2 = &a[1][0];
p1+5 is a legal expression and given the layout of a, it is equal to p2. Hence, if we use:
int* p3 = p1 + 6;
why should that not be equivalent to
int* p3 = p2 + 1;
If p2 + 1 is legal expression, why should p1 + 6 not be a legal expression?
From a purely pedantic interpretation of the standard, using p1 + 6 is cause for undefined behavior. However, it is possible that the standard does not adequately address the issue when it comes to 2D arrays.
In conclusion
From all practical points of view, there is no problem in using p1 + 6.
From a purely pedantic point of view, using p1 + 6 is undefined behavior.
Either an int pointer or a char pointer should work, but the operation should differ slightly in these two cases. Assuming sizeof(int) is 4. pc += sizeof(int) moves the pointer 4 bytes forward, but pi += sizeof(int) would move 4 times 4 bytes forward. If you want to use an int pointer, you should use pi ++.
EDIT: sorry about the answer above, using an int pointer does not comply with C99 (although it usually practically works). The reason is explained well in the original question: pointer goes across an array is not well defined in the standard. If you use an int pointer, you would start from a[0], which is a different array from a[1]. In this case, an a[0] int pointer cannot legally (well-defined) point to a[1] element.
SECOND EDIT: Using a char pointer is valid, because the following reason given by the original answer:
the array as a whole must be working when given to memset, memmove or memcpy with the sizeof. It must also be possible to iterate over the whole array with a (char *).
From section 6.5.6 "Additive Operators"
For the purposes of these operators, a pointer to an object that is not an element of an
array behaves the same as a pointer to the first element of an array of length one with the
type of the object as its element type.
So it is reasonable.

Why pointers and arrays are not same : Need justification on quote

I need the following quote especially the bold text , to be justified.
... This would tend to imply that
somehow source[i] is the same as *(p+i).
In fact, this is true, i.e wherever one writes a[i] it can be replaced with *(a + i) without any problems.
In fact, the compiler will create the same code in either case. Thus we see
that pointer arithmetic is the same thing as array indexing. Either syntax produces the
same result.
This is NOT saying that pointers and arrays are the same thing, they are not. We are only
saying that to identify a given element of an array we have the choice of two syntaxes,
one using array indexing and the other using pointer arithmetic, which yield identical
results.
This is quoted from the pdf
A TUTORIAL ON POINTERS AND ARRAYS IN C
by Ted Jensen
Version 1.2 (PDF Version)
Sept. 2003
P.No : 19
The expressions a[i] and *(a + i) are the same by definition. The C and C++ standards define the expression syntax a[i] to be always equivalent to *(a + i), to the point where a[i] and i[a] are interchangeable.
That does not tell you anything about the relationship between pointers and arrays, because, technically, in both a[i] and *(a + i), a is an expression of pointer type. The [] operator takes a pointer expression on the left, not an array expression; and the + operator only operates on a pointer and an integer -- not an array and an integer.
That you can use an array in place of a is simply a result of the fact that an expression of array type may be implicitly converted to an rvalue expression of pointer type.
Array of type T may behave similar to pointer of type T, but their types are different and this compiler treat these as different types.
Let's understand with some pragmatic examples.
Example 1 where you can see the difference.
int a[1200] = {0};
int *p = a;
assert(sizeof a != sizeof p);
Example 2 where you can see the difference.
/* test.c */
#include<stdio.h>
#include"head.h"
struct token id_tokens[10];
int main()
{
printf("In original file: %p",id_tokens);
testing();
}
/* head.h */
struct token {
int temp;
};
/* test1.c with v1 */
#include<stdio.h>
#include"head.h"
extern struct token* id_tokens;
void testing () {
printf("In other file %p",id_tokens);
}
/* test1.c with v2 */
#include<stdio.h>
#include"head.h"
extern struct token id_tokens[];
void testing () {
printf("In other file %p",id_tokens);
}
Output with v1: Output : In original file: 0x601040In other file
(nil) Output with v2: Output : In original file: 0x601040In other
file 0x601040
Example 2 picked from extern declaration, T* v/s T[]
Further readings on array and pointer: C-faq
An array is a block of consecutive elements, each of the same type. For example, a block of 200 integers.
A pointer is a small object that can identify a memory location.
These are nothing like each other. The array could be gigabytes in size but the pointer is 8 bytes at most (on popular systems).
Saying "arrays and pointers are the same" or "an array is a constant pointer" or other such garbage makes as much sense as saying that a house is an envelope.
All of that has nothing to do with talking about a[n] versus *(a + n). That is a feature of the language syntax, which is a different topic to the layout of variables in memory.
We could ban the use of [] outside of declarators and C would still have the same functionality, but the code would be harder to read. The rules of the language say that you can write a[n] as a more readable version of *(a + n); and they have the same effect.
Pointers and array names are different
Yes.
Consider the below code snippet to get the difference
int a[3];
int *p = a;
a++; /* This is a error */
p++;
printf("%d\n",*p);
Array name can't be a modifiable lvalue.(According to the standard)
Where as a pointer can be.
Adding another example where you can see a difference
printf("%d\n",sizeof(a)/sizeof(*a));
printf("%d\n",sizeof(p)/sizeof(*p));
Number of elements in a array can be given by the first line but not by the second one. Why? Array name and Pointers are different

Access structure members with a pointer

In C, I am having a structure like this
typedef struct
{
char *msg1;
char *msg2;
.
.
char *msgN;
}some_struct;
some_struct struct1;
some_struct *pstruct1 = &struct1;
I want to keep a pointer or a varible which when incremented or decremented, gives the next/last member variable of this structure. I do not want to use array of char * since it is already designed like this.
I tried using the union and structure combination, but I don't know how to write code for that.
Thought iterator may help but this is C.
Any suggestions ?
You can't do that, safely. You can take a chance that the adjacent character pointers are really adjacent (with no padding) as if they were in an array, but you can't be sure so that's pretty much straight into the undefined behavior minefield.
You can abstract it to an index, and do something like:
char * get_pointer(some_struct *p, int index)
{
if(index == 0)
return p->msg1;
if(index == 1)
return p->msg2;
/* and so on */
return NULL;
}
Then you get to work with an index which you can increment/decrement freely, and just call get_pointer() to map it to a message pointer when needed.
You can do this using strict C, but you need to take certain precautions to ensure compliance with the standard. I will explain these below, but the precautions you need to take are:
(0) Ensure there is no padding by including this declaration:
extern int CompileTimeAssert[
sizeof(some_struct) == NumberOfMembers * sizeof(char *) ? 1 : -1];
(1) Initialize the pointer from the address of the structure, not the address of a member:
char **p = (char **) (char *) &struct1;
(I suspect the above is not necessary, but I would have to insert more reasoning from the C standard.)
(2) Increment the pointer in the following way, instead of using ++ or adding one:
p = (char **) ((char *) p + sizeof(char *));
Here are explanations.
The declaration in (0) acts as a compile-time assertion. If there is no padding in the struct, then the size of the struct equals the number of members multiplied by the size of a member. Then the ternary operator evaluates to 1, the declaration is valid, and the compiler proceeds. If there is padding, the sizes are not equal, the ternary operator evaluates to -1, and the declaration is invalid because an array cannot have a negative size. Then the compiler reports an error and terminates.
Thus, a program containing this declaration will compile only if the struct does not have padding. Additionally, the declaration will not consume any space (it only declares an array that is never defined), and it may be repeated with other expressions (that evaluate to an array size of 1 if their condition is true), so different assertions may be tested with the same array name.
Items (1) and (2) deal with the problem that pointer arithmetic is normally guaranteed to work only within arrays (including a notional sentinel element at the end) (per C 2011 6.5.6 8). However, the C standard makes special guarantees for character types, in C 2011 6.3.2.3 7. A pointer to the struct may be converted to a pointer to a character type, and it will yield a pointer to the lowest addressed byte of the struct. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.
In (1), we know from C 2011 6.3.2.3 7, that (char *) &struct1 is a pointer to the first byte of struct1. When converted to (char **), it must be a pointer to the first member of struct1 (in particular thanks to C 2011 6.5.9 6, which guarantees that equal pointers point to the same object, even if they have different types).
Finally, (2) works around the fact that array arithmetic is not directly guaranteed to work on our pointer. That is, p++ would be incrementing a pointer that is not strictly in an array, so the arithmetic is not guaranteed by 6.5.6 8. So we convert it to a char *, for which increments are guaranteed to work by 6.3.2.3 7, we increment it four times, and we convert it back to char **. This must yield a pointer to the next member, since there is no padding.
One might claim that adding the size of char ** (say 4) is not the same as four increments of one char, but certainly the intent of the standard is to allow one to address the bytes of an object in a reasonable way. However, if you want to avoid even this criticism, you can change + sizeof(char *) to be +1+1+1+1 (on implementations where the size is 4) or +1+1+1+1+1+1+1+1 (where it is 8).
Take the address of the first member and store it to char **:
char **first = &struct1.msg1;
char **last = &struct1.msg1 + sizeof(some_struct) / sizeof(char *) - 1;
char **ptr = first; /* *ptr is struct.msg1 */
++ptr; /* now *ptr is struct1.msg2 */
This assumes that the structure only contains char * members.

Does C99 guarantee that arrays are contiguous?

Following an hot comment thread in another question, I came to debate of what is and what is not defined in C99 standard about C arrays.
Basically when I define a 2D array like int a[5][5], does the standard C99 garantee or not that it will be a contiguous block of ints, can I cast it to (int *)a and be sure I will have a valid 1D array of 25 ints.
As I understand the standard the above property is implicit in the sizeof definition and in pointer arithmetic, but others seems to disagree and says casting to (int*) the above structure give an undefined behavior (even if they agree that all existing implementations actually allocate contiguous values).
More specifically, if we think an implementation that would instrument arrays to check array boundaries for all dimensions and return some kind of error when accessing 1D array, or does not give correct access to elements above 1st row. Could such implementation be standard compilant ? And in this case what parts of the C99 standard are relevant.
We should begin with inspecting what int a[5][5] really is. The types involved are:
int
array[5] of ints
array[5] of arrays
There is no array[25] of ints involved.
It is correct that the sizeof semantics imply that the array as a whole is contiguous. The array[5] of ints must have 5*sizeof(int), and recursively applied, a[5][5] must have 5*5*sizeof(int). There is no room for additional padding.
Additionally, the array as a whole must be working when given to memset, memmove or memcpy with the sizeof. It must also be possible to iterate over the whole array with a (char *). So a valid iteration is:
int a[5][5], i, *pi;
char *pc;
pc = (char *)(&a[0][0]);
for (i = 0; i < 25; i++)
{
pi = (int *)pc;
DoSomething(pi);
pc += sizeof(int);
}
Doing the same with an (int *) would be undefined behaviour, because, as said, there is no array[25] of int involved. Using a union as in Christoph's answer should be valid, too. But there is another point complicating this further, the equality operator:
6.5.9.6
Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space. 91)
91) Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. If prior invalid pointer operations (such as accesses outside array bounds) produced undefined behavior, subsequent comparisons also produce undefined behavior.
This means for this:
int a[5][5], *i1, *i2;
i1 = &a[0][0] + 5;
i2 = &a[1][0];
i1 compares as equal to i2. But when iterating over the array with an (int *), it is still undefined behaviour, because it is originally derived from the first subarray. It doesn't magically convert to a pointer into the second subarray.
Even when doing this
char *c = (char *)(&a[0][0]) + 5*sizeof(int);
int *i3 = (int *)c;
won't help. It compares equal to i1 and i2, but it isn't derived from any of the subarrays; it is a pointer to a single int or an array[1] of int at best.
I don't consider this a bug in the standard. It is the other way around: Allowing this would introduce a special case that violates either the type system for arrays or the rules for pointer arithmetic or both. It may be considered a missing definition, but not a bug.
So even if the memory layout for a[5][5] is identical to the layout of a[25], and the very same loop using a (char *) can be used to iterate over both, an implementation is allowed to blow up if one is used as the other. I don't know why it should or know any implementation that would, and maybe there is a single fact in the Standard not mentioned till now that makes it well defined behaviour. Until then, I would consider it to be undefined and stay on the safe side.
I've added some more comments to our original discussion.
sizeof semantics imply that int a[5][5] is contiguous, but visiting all 25 integers via incrementing a pointer like int *p = *a is undefined behaviour: pointer arithmetics is only defined as long as all pointers invoved lie within (or one element past the last element of) the same array, as eg &a[2][1] and &a[3][1] do not (see C99 section 6.5.6).
In principle, you can work around this by casting &a - which has type int (*)[5][5] - to int (*)[25]. This is legal according to 6.3.2.3 §7, as it doesn't violate any alignment requirements. The problem is that accessing the integers through this new pointer is illegal as it violates the aliasing rules in 6.5 §7. You can work around this by using a union for type punning (see footnote 82 in TC3):
int *p = ((union { int multi[5][5]; int flat[25]; } *)&a)->flat;
This is, as far as I can tell, standards compliant C99.
If the array is static, like your int a[5][5] array, it's guaranteed to be contiguous.

Resources