Yes. The size of a type is always a multiple of its alignment. S(u8) on its own has an unstable layout, but realistically, the compiler will most likely give it size 1 and alignment 1 (in bytes). Adding #[repr(align(32))] means that alignment will be increased if it wasn't at least 32 yet.
Alignment 32 of a data type means that every value of that type will start at a memory address that's a multiple of 32. The 31 extra bytes are padding and contain no data, but they take up space: E.g. an array/slice β[S]β of these S's
#[repr(align(32))]
struct S(u8);
is consisting mostly of padding: 1 byte of data, then 31 bytes of padding, then 1 byte of data again, etc., and this makes sure that each data byte has an address that's a multiple of 32. [1]
Increasing the alignment like this can sometimes make sense to make sure values land on different cache lines to make parallel code more efficient; or it could, together with repr(C), make sense if you need to conform to some ABI to control layout more precisely. (And there's probably other use-cases I canβt think of right now.) Other than that, it's mostly a disadvantage, because it increases memory consumption, so don't use #[repr(align(32))] unless you know why you need it.
The only other thing that I can see would require this would be using vector extensions on architectures (e.g. AVX, SSE, SSSE, AVX2, etc.). These extensions usually have alignment requirements of one kind or another, and they're usually enforced.