Perhaps nitpicky, but I wouldn’t suggest recommending VLAs in a document like this. The consensus seems to be that it’s probably never wise to use them. They were also made optional in C11 (meaning compilers no longer have to support them and you have to test for __STDC_NO_VLA__ to check support). It’s basically syntactic sugar for the same thing alloca() does, which has all the same problems as VLAs:

The basic argument against them goes something like this: if the variable size argument(s) for your VLAs could end up being very large at runtime, they could overflow stack space and cause a crash. If your answer to this proposed crash (for a given VLA usage) is that your VLA size arguments are already constrained to stack-reasonable sizes, then it would be more efficient, compatible, and simple to simply declare a fixed-length stack array of the maximum possible size (since stack allocations just adjust a stack frame pointer). If you really do need the possibility of very large sizes and don’t want to possibly crash, the only sane approach is going to be to use heap allocatiors like malloc() and friends.

I agree with you, and I don’t find this nitpicky at all. Use of VLAs is lately discouraged in the kernel, and there’s an active effort to remove them[1]. They’re not secure, and have slower performance, so a document about pleasant C should in my opinion discourage them, or not mention them at all, but not do the opposite.

If you often have to work with 3D arrays then you should definitely put an extra layer there that multiplies for you, but I didn’t do that here, because the example in the page was about convenience, and I wanted to show mallocing that can be used in exactly the same way with fread.

VLAs could be more fair if there would be a way to map them to a custom heap allocator, there’s nothing in the spec itself that dictates the allocation to be intertwined with your stack frame and obvious reasons why you would want to avoid just that. The whole principle is to get access to dynamic allocation tied to the scope of ‘auto’, what pool it is taken from is secondary - but with sizeof() being possibly dynamic, get something that isn’t malloc heap or compiler managed stack.

For the leading-break, this is just a way to put a break for the previous case. In fact, my auto-formatter just moves it to the normal place for the previous case. It’s another way to remember to always break your cases I guess.