-#define GARY_INIT(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), 0)
-#define GARY_INIT_ZERO(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), 1)
+/**
+ * Create a new growing array, initially containing @n elements,
+ * and let @ptr point to its first element. The memory used by the
+ * array is allocated by <<basics:xmalloc()>>.
+ **/
+#define GARY_INIT(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), &ucw_allocator_std)
+
+/**
+ * Create a growing array like GARY_INIT() does, but all newly
+ * allocated elements will be automatically zeroed.
+ **/
+#define GARY_INIT_ZERO(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), &ucw_allocator_zeroed)
+
+/**
+ * Create a growing array like GARY_INIT() does, but based upon the given
+ * <<alloc:,generic allocator>>.
+ **/
+#define GARY_INIT_ALLOC(ptr, n, a) (ptr) = gary_init(sizeof(*(ptr)), (n), (a))
+
+/**
+ * Create a growing array, initially containing 0 elements, but with enough
+ * space to keep @n of them without needing reallocation. The @ptr variable
+ * will point to the first element of the array.
+ **/