For a two-dimensional array
T a[N][M];
a pointer to this array will look like
T (*ap)[M];
so your prototype add function should look like
void add(int (*a)[COLS], int (*b)[COLS]) {...}
and be called
int main(void) { int a[ROWS][COLS]; int b[ROWS][COLS]; ... add(a, b);
However, this code reveals several problems. Firstly, your add function relies on information that is not passed through a parameter list, but through a global variable or symbolic constant; namely, the number of rows (the number of columns is explicitly specified in the parameter type). This tightly connects the add function with this particular program and makes it difficult to reuse elsewhere. For your purposes this may not be a problem, but in general you want your functions to communicate with their callers through a list of parameters and return values.
The second problem is that, as written, your function will only work for ROWS row matrices and COLS columns; if you want to add matrices of different sizes to the same program, this approach will not work. Ideally, you want to add a function that can deal with matrices of different sizes, that is, you need to pass the dimensions as separate parameters. It also means that we must change the type of pointer that we pass.
One possible solution is to process your matrices as simple pointers to int and manually calculate the offsets instead of using indices:
void add (int *a, int *b, size_t rows, size_t cols) { size_t i; for (i = 0; i < rows; i++) { size_t j; for (j = 0; j < cols; j++) { *(a + cols * i + j) += *(b + cols * i + j); } } }
and name it like this:
int main(void) { int a[ROWS][COLS] = {...}; int b[ROWS][COLS] = {...}; int c[ROWS2][COLS2] = {...}; int d[ROWS2][COLS2] = {...}; ... add(a[0], b[0], ROWS, COLS); add(c[0], d[0], ROWS2, COLS2); ... }
Types a [0] and b [0] are "arrays of COLS-elements int"; in this context, they will both be implicitly converted to a "pointer to int". Similarly, c [0] and d [0] are also implicitly converted to int *. Offsets in the add () function work because 2D arrays are contiguous.
EDIT I just realized that I was responding to the cafe example, not the OP, and the cafe edited its response to show something very similar to my example. C'est la guerre. I will leave my example, just to show a slightly different approach. I also think that the phrase about the transfer of information between functions and subscribers is valuable.