The ugly MaxFactors constant, along with the problem of there being such a thing as a maximum number of factors, and the problem of telling the calling program how many factors you actually found along with , and this is a big one, the requirement of callers to clean up the memory allocated by factors can be solved with vectors.

The other trick to note, is that if n has no factors < sqrt(n) then ether sqrt(n) is a factor (n is the square of a prime), or n is a prime. sqrt is mildly expensive so I jumped through some hoops to minimse the number of times it's called.

Code:

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <iterator>
typedef std::vector<unsigned> factors_t;
factors_t factors(unsigned n) {
if(n < 2) return factors_t(1,n);
factors_t v;
while(n % 2 == 0) { v.push_back(2); n/=2; }
unsigned max = static_cast<unsigned>(ceil(sqrt(n)));
for(unsigned fact = 3; fact <= max; fact += 2) {
if(n % fact == 0) {
do {
v.push_back(fact);
n/=fact;
} while(n % fact == 0);
max = static_cast<int>(ceil(sqrt(n)));
}
}
if(n > 1) v.push_back(n);
return v;
}
int main(int argc, char *argv[]) {
unsigned n = (argc>1)?atoi(argv[1]):2*2*3*5*7*13*17;
factors_t v = factors(n);
std::cout << n << " has " << v.size() << " factors" << std::endl;
std::copy(v.begin(),v.end()-1,std::ostream_iterator<unsigned>(std::cout,"*"));
std::cout << v.back() << std::endl;
return 0;
}