Here's a short C program that prompts the user for a number, creates a variable-length array of ints of that size, and then uses pointer arithmetic to step over the elements that were allocated:
#include <stdio.h>
int main() {
/* Read a size from the user; inhibits compiler optimizations. */
int n;
scanf("%d", &n); // Yes, I should error-check. :-)
/* We now have a VLA. */
int arr[n];
/* What is the type of &arr? */
void* ptr = (&arr) + 1;
/* Seems like this skipped over things properly... */
printf("%p\n", arr);
printf("%p\n", ptr);
}
You can try this on ideone if you'd like. The output suggests that the line
void* ptr = (&arr) + 1;
takes the address of arr and, in a size-aware way, steps over all n of the elements in the variable-length array.
If this were not a variable-length array, I'd be completely comfortable with how this works. The compiler would know the type of arr (it would be int (*) [K] for some constant K), so when we add one to &arr it could skip over the right number of bytes.
It's clear how, at runtime, we could evaluate (&arr) + 1. The compiler stashes the size of arr somewhere on the stack, and when we add one to (&arr) it knows to load that size in order to compute how many bytes to skip over.
However, what I don't know is what the language says the type of the expression &arr is. Is it assigned some static type that indicates it's a variable-length array (something like int (*) [??])? Does the spec say "the type of the expression is int (*) [K], where K is whatever size is assigned to the array at runtime?" Does the spec disallow taking the address of a variable-length array, and the compiler just happens to allow it?
sizeofoperator evaluates the operand to determine the size of the variable length array object, so+must do the same thing. See C.2011 - 6.5.6/10.