```
void setZeroes(int** matrix, int matrixRowSize, int matrixColSize) {
int delRowOne = 0; // aux var
// scan row 1 for zeros
for (int rowOneScan = 0; rowOneScan < matrixColSize; rowOneScan++) {
if (matrix[0][rowOneScan] == 0) {
delRowOne = 1;
break;
}
}
// zero out rows from bottom to top, storing column deletion mark '0' in row 0
for (int row = matrixRowSize-1; row > 0; row--) { // skip 0th row
int clearRow = 0; // aux var
for (int col = matrixColSize-1; col > -1; col--) { // hit 0th col
if (matrix[row][col] == 0) {
matrix[0][col] = 0;
clearRow = 1;
}
}
for (int col = matrixColSize-1; col > -1; col--) {
if (clearRow) {
matrix[row][col] = 0;
}
}
}
// scan row 1 and delete columns based on 0's
for (int col = 0; col < matrixColSize; col++) {
if (matrix[0][col] == 0) {
for (int row = 0; row < matrixRowSize; row++) {
matrix[row][col] = 0;
}
}
if (delRowOne) {
matrix[0][col] = 0;
}
}
}
```

Basically it reserves the first row as a bit-map for clearing columns. Rows n through 1 are cleared and whenever a 0 was present, that column was flagged in row 0. At the end, row 0 is parsed and relevant columns are cleared. Finally, if row 0 must be cleared, it is cleared at the end.