The define way is static allocation, and only helps you organize your constants. Imagine you'd need 40 now instead of 20, you just change MAX_SIZE to 40, rather than looking through your code where you use the number 20.
The second way however does *not* work, because max_size is not constant.
The main idea behind dynamic allocation is optimized memory usage. Having char buffer uses 200 Bytes, no matter if you need them or not. char *buffer uses 4 Bytes, and you can allocate as much as you need - when you need it.
There are still systems out there that have few to no memory, and you have to use it wisely (I just recently talked to a guy that wanted to run a game of his on a calculator with 118 KB Memory - asking a similar thing about malloc/free).
Dynamic allocation makes more sense with Data structures tho. Grab a struct that holds a pointer to its next element, allocate them with malloc when you need them.
Create vectors of objects, in-time when required - no limitation to size on compile time. Need one more, just add another.
Doesnt work with static sized arrays.