Why this code don't work?
    *i[0] = 1;
i is a pointer, so i[0] considers it (the pointer) to be a pointer to the start of an array, obtain the element at position 0 (the one you should assign) and assign it a 1 value.  If you try to dereference it again, as the array element itself is not a pointer (but an integer value) you will get an error from the compiler.  What you want to do is to use the array element itself
    i[0] = 1;
For the same reason, to print the array element, you need to use i[0] again and not the expression you used.
Why is this done with malloc()? Malloc is a general purpose dynamic memory allocator, it gathers a continous block of memory to fit the size you specify and returns to you a pointer to the result.  You can then use that pointer as the address of the array you want to handle, or as a structure to be filled up with data.... etc.  The void * pointer that malloc() returns can be converted to any other pointer type, making it flexible for any purpose.