Pavel's answer shows how to perform recursion. However, a function which takes only two arguments (number of loops and maximum value) does not have enough context to actually print the numbers as in your example. For that, you'll have to keep track of some extra information. One way to do this, is the following:
void _print_loop(int *values, int width, int cur_col, int max) {
if (cur_col == width) {
for (int i = 0; i < width; i++) {
printf("%d%c", values[i], (i < width - 1) ? ' ' : '\n');
}
} else {
for (int i = 0; i < max; i++) {
values[cur_col] = i;
_print_loop(values, width, cur_col + 1, max);
}
}
}
void print_loop(int width, int max) {
int values[width];
memset(values, 0, width * sizeof(int));
_print_loop(values, width, 0, max);
}
Now print_loop(3, 2)
behaves as expected.
Edit: actually, one can write a two-argument function to do this, through the use of static
variables which are initialized upon receiving a positive width
argument. After this initialisation stage the function then performs its recursion using negative values. Obviously, the resulting code is horrible, but I'll post it anyway, for the sake of completeness:
void print_loop(int width, int max) {
static int max_width;
static int *values;
if (width > 0) {
max_width = width;
if ((values = calloc(width, sizeof(int))) == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
print_loop(-width, max);
free(values);
}
else if (width == 0) {
for (int i = 0; i < max_width; i++) {
printf("%d%c", values[i], (i < max_width - 1) ? ' ' : '\n');
}
}
else {
for (int i = 0; i < max; i++) {
values[-width - 1] = i;
print_loop(width + 1, max);
}
}
}