As @HansPassant and others noted, variable alignment on the stack is an implementation detail. You can't even be sure that any of them will be on the stack once optimization is enabled (unless you take an address of it) - each can be optimized to a register.
Just to illustrate: the test program
#include <stdio.h>
#include <windows.h>
int main() {
int x = 1, y = 2, z = 3;
printf("%d,%d,%d,%d\n",&y-&x,&z-&y,(BYTE*)&y-(BYTE*)&x,(BYTE*)&z-(BYTE*)&y);
}
prints here (win7 x64, vs2012 x86 compiler):
>cl /nologo t.c >nul && t.exe
2,-1,8,-4
>cl /Ox /nologo t.c >nul && t.exe
-2,1,-8,4
>cl /RTC1 /Ox /nologo t.c >nul && t.exe
-3,-3,-12,-12
In the last case, /RTC inserts gaps between variables to detect out-of-bounds access.
Regarding the default alignment, compilers adhere to Intel's recommendations that owe to the fact that x86 suffers a penalty while accessing unaligned data. Here, specifically, it's Intel® 64 and IA-32 Architectures Optimization Reference Manual, section 3.6.7 Stack Alignment:
Performance penalty of unaligned access to the stack happens when a
memory reference splits a cache line. This means that one out of eight
spatially consecutive unaligned quadword accesses is always penalized,
similarly for one out of 4 consecutive, non-aligned double-quadword
accesses, etc.
Aligning the stack may be beneficial any time there are
data objects that exceed the default stack alignment of the system.
For example, on 32/64bit Linux, and 64bit Windows, the default stack
alignment is 16 bytes, while 32bit Windows is 4 bytes.
Assembly/Compiler Coding Rule 55. (H impact, M generality) Make sure
that the stack is aligned at the largest multi-byte granular data type
boundary matching the register width.
For longer types (floating-point), even higher alignments are recommended for the same purpose.