A number of methods are possible.
A generalization on b49P23TIvg's method would be to initialize the array by filling it with an invalid value. Could be zero if all valid values would be greater than zero. -1 is a popular choice if a valid value is greater than or equal to 0. Or INT_MAX or INT_MIN if valid values would be reasonable positive and negative values. In an array of pointers, NULL is a good default invalid value. What you choose depends on your requirements.
If you start filling the array from the beginning and insert each new value in the next available slot, then simply keep a count of how many values you've already input. That count would then be the index for the next value to be stored and then you increment the count. You'd have to think of how to apply that to a 2-D array.
Offered just for completeness: If it's an array of structs, then you could add a field in the struct that would flag whether this struct has already been written to.
A variation of the last two just occurred to me. Have two arrays, one that contains the values and the other that flags whether the indexed element in the values array is free or has been written to: a flag of one means it's been written to, a flag of zero means it's free to be written to. For example, when you write to values, you also write a 1 to flags. Then to write to an element:
values[i][j] = new_value;
I'm sure we could come up with more ideas.
Another thought, a variation on that last one. Add a dimension to the array that would hold the flags; eg:
// Plane 0 of the array contains the data values,
// Plane 1 of the array contains the flags
array[i][j] = new_value;