#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define ROW_PTR_BLOCK_SIZE(TYPE, ROW_COUNT) ROW_COUNT * sizeof(TYPE *)
#define ROW_BLOCK_SIZE(TYPE, COL_COUNT) COL_COUNT * sizeof(TYPE)
#define BLOCK_SIZE(TYPE, ROW_COUNT, COL_COUNT) ROW_PTR_BLOCK_SIZE(TYPE, ROW_COUNT) + ROW_COUNT * ROW_BLOCK_SIZE(TYPE, COL_COUNT)
#define ALLOCATE(STACK_TOP, TARGET, TYPE, COUNT) do{TARGET = (TYPE *)STACK_TOP; STACK_TOP += COUNT * sizeof(TYPE);}while(0)

int func(int a1_row, int a1_col, int a2_row, int a2_col, int a3_row, int a3_col, double ***a1_dst, int ***a2_dst, float ***a3_dst)
{
    char *stack[3];
	char *stack_top[3];
	int stack_size[3] =
	{
		BLOCK_SIZE(double, a1_row, a1_col),
		BLOCK_SIZE(int, a2_row, a2_col),
		BLOCK_SIZE(float, a3_row, a3_col)
	};

	double **a1 = NULL;
	int **a2 = NULL;
	float **a3 = NULL;
	int i;
	int succeeded = 1;

	for(i = 0; i < 3 && succeeded; ++i)
	{
		stack_top[i] = stack[i] = (char *)malloc(stack_size[i]);
		if(!stack[i])
			succeeded = 0;
	}

	if(!succeeded)
	{
		for(i = 0; i < 3; ++i)
			if(!stack[i])
				break;
		for(i = i - 1; i >= 0; --i)
			free(stack[i]);
		return 0;
	}

	ALLOCATE(stack_top[0], a1, double *, a1_row);
	for(i = 0; i < a1_row; ++i)
		ALLOCATE(stack_top[0], a1[i], double, a1_col);

	ALLOCATE(stack_top[1], a2, int *, a2_row);
	for(i = 0; i < a2_row; ++i)
		ALLOCATE(stack_top[1], a2[i], int, a2_col);
	
	ALLOCATE(stack_top[2], a3, float *, a3_row);
	for(i = 0; i < a3_row; ++i)
		ALLOCATE(stack_top[2], a3[i], float, a3_col);

	assert(stack[0] + stack_size[0] == stack_top[0]);
	assert(stack[1] + stack_size[1] == stack_top[1]);
	assert(stack[2] + stack_size[2] == stack_top[2]);

	*a1_dst = a1;
	*a2_dst = a2;
	*a3_dst = a3;

	return 1;
}

#define A1_ROW (300)
#define A1_COL (200)
#define A2_ROW (400)
#define A2_COL (300)
#define A3_ROW (500)
#define A3_COL (400)

int main(void)
{
	double **a1 = NULL;
	int **a2 = NULL;
	float **a3 = NULL;
	int result = func(A1_ROW, A1_COL, A2_ROW, A2_COL, A3_ROW, A3_COL, &a1, &a2, &a3);
	
	printf("result = %d\n", result);

	if(result)
	{
		free(a1);
		free(a2);
		free(a3);
	}

	return 0;
}