How to Write a Factorial Program in C: The Ultimate Guide
A factorial is the product of all positive integers from one through a nonnegative integer n. It is written n!, with the special case 0! = 1. The sequence begins 1, 1, 2, 6, 24 and 120 for inputs zero through five.
A factorial program in C is a useful beginner exercise because it combines loops, functions, command-line input and numeric types. It also demonstrates a real engineering problem: factorial values grow so quickly that unchecked integer arithmetic can overflow even when the algorithm looks correct.
For a positive integer n, factorial is n × (n−1) × ... × 2 × 1. Negative integers do not have a factorial in the ordinary integer definition used here. Zero factorial is one so that many combinatorial identities work consistently.
For example, 5! = 5 × 4 × 3 × 2 × 1 = 120. Factorials appear in permutations and combinations, probability calculations and analyses of algorithms, but real applications often avoid constructing huge factorials when a more stable expression is possible.
An iterative implementation starts with one and multiplies by each integer from two through n. It uses constant additional space. The code below assumes the caller has already validated a safe input range; validation is a separate responsibility.
The type unsigned long long is guaranteed by the C standard to provide at least 64 value bits. That is enough for factorials through 20, but not for 21, so an unrestricted loop would eventually overflow.
#include <stdio.h>
unsigned long long factorial(unsigned int n) {
unsigned long long product = 1ULL;
for (unsigned int i = 2; i <= n; ++i) {
product *= i;
}
return product;
}
int main(void) {
printf("%llu\n", factorial(5)); /* 120 */
return 0;
}
For a robust standalone program, check that exactly one argument was supplied and convert it with strtol(). Clear errno before conversion and check the end pointer so input such as 12x is rejected rather than silently treated as 12.
Limit values to zero through 20 when using unsigned long long as the result type. That rule makes the example safe on conforming C implementations without relying on an assumed machine-specific extension.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s N (0..20)\n", argv[0]);
return 2;
}
errno = 0;
char *end = NULL;
long n = strtol(argv[1], &end, 10);
if (errno != 0 || end == argv[1] || *end != '\0'
|| n < 0 || n > 20) {
fprintf(stderr, "N must be a whole number from 0 to 20\n");
return 2;
}
unsigned long long result = 1ULL;
for (long i = 2; i <= n; ++i) {
result *= (unsigned long long)i;
}
printf("%ld! = %llu\n", n, result);
return 0;
}
Save the validated implementation in a file named factorial.c and compile with a C11-compatible compiler. Enable warnings during learning so narrowing conversions or suspicious code are visible. A compiler warning may reveal a real bug even when one test run appears to succeed.
Run several boundary tests, including zero, one, five, twenty, a negative value, an empty argument and a string with extra characters. Confirm not only the result but the error status for invalid input.
cc -std=c11 -Wall -Wextra -Wconversion factorial.c -o factorial
./factorial 5
./factorial 0
./factorial 21 # should report an invalid range
The result for 20! is 2,432,902,008,176,640,000 and fits within a 64-bit unsigned integer. 21! is larger than the maximum guaranteed unsigned long long value. Unsigned overflow wraps according to the type’s modulus; it does not make the mathematical result correct.
If a reusable factorial function must accept a wider range, check before multiplying: if (result > ULLONG_MAX / i) means the next product would not fit. Return an explicit error instead of quietly producing a wrapped number. The C integer limits reference documents the relevant type bounds.
Recursion expresses n! = n × (n−1)! with a base case of zero or one. It can be elegant for teaching, but each call consumes stack space, and it does not solve integer overflow. Iteration is normally simpler for a bounded factorial calculator.
Never send an arbitrary huge input into naive recursion. Validate the range and ensure the base case is reached. The recursive form is best viewed as a demonstration of the mathematical recurrence, not a performance improvement.
unsigned long long factorial_recursive(unsigned int n) {
if (n <= 1) return 1ULL;
return (unsigned long long)n * factorial_recursive(n - 1);
}
/* Call only after validating n <= 20. */
If an application needs the exact digits of 100! or larger values, use a maintained arbitrary-precision integer library, such as GNU MP where appropriate for the project’s licensing and platform requirements. A float or double may represent approximate magnitudes but will not preserve all the exact decimal digits.
In probability or scientific work, calculating log(n!) or using stable combinatorial formulas can sometimes avoid enormous intermediate values. The correct technique depends on whether you need an exact integer, a ratio or only an approximate scale.
The simple iterative factorial takes O(n) multiplications and O(1) extra space when using a fixed-width result type. The recursive version also performs O(n) multiplications but typically needs O(n) call-stack space. With arbitrary-precision integers, multiplication cost grows as the number of digits increases.
For repeated factorial queries, a precomputed table up to a validated maximum can be helpful. In most small programs, clarity and correct overflow handling matter more than caching twenty values.
Check 0! explicitly, reject negatives, ensure the input parser rejects trailing text, and test that twenty is accepted but twenty-one is rejected. Use the correct printf format for the result type, and avoid converting a large unsigned number into a narrower signed type.
One-off manual tests are useful, but automated test cases make later changes safer. Verify successful exit status for valid input and nonzero status for malformed input. The C strtol reference describes conversion and range-error behavior.
A correct C factorial program needs more than a loop: it must define the valid mathematical domain, choose a numeric type, check conversion, avoid overflow and report failures cleanly. Start with the validated zero-to-twenty example, then choose an arbitrary-precision approach if your real requirements exceed that range. The broader C data structures guide provides related practice with arrays and memory management.
