The classic way this exercise was taught — Turbo C’s <graphics.h> with initgraph() and circle(x, y, r) — hasn’t compiled on a mainstream system in decades: graphics.h was a Borland DOS library, not part of C. But the underlying question is still excellent: how does a computer decide which pixels form a circle? The answer is the midpoint circle algorithm (Bresenham’s circle), which draws a perfect circle using only integer arithmetic — no floating point, no sqrt(), no trigonometry. This page implements it in portable C that renders the circle as ASCII output in any terminal, tested and warning-free.
How the Midpoint Circle Algorithm Works — Step by Step
- Exploit symmetry: a circle is 8-way symmetric. Compute just one octant (from the top, 45° down) and mirror every point into the other seven octants for free.
- Start at the top: (x, y) = (0, r), with a decision variable
d = 1 − r. - At each step, move east or southeast: the decision variable tracks whether the midpoint between the two candidate pixels lies inside or outside the ideal circle. Inside (
d < 0): keep y, updated += 2x + 3. Outside: decrement y, updated += 2(x − y) + 5. - Stop when x > y — the octant is complete, and symmetry has already painted the rest.
The entire circle costs ~r/√2 iterations of integer adds and shifts — this is why every graphics library from DOS BGI to modern GPUs rasterizes circles this way.
C Program to Draw a Circle (Midpoint Algorithm, ASCII Output)
#include <stdio.h>
#include <string.h>
#define SIZE 41 /* odd, so the centre is a single cell */
static char grid[SIZE][SIZE];
static void plot(int cx, int cy, int x, int y)
{
/* plot all 8 symmetric octant points, if inside the grid */
int px[8], py[8], i;
px[0] = cx + x; py[0] = cy + y;
px[1] = cx - x; py[1] = cy + y;
px[2] = cx + x; py[2] = cy - y;
px[3] = cx - x; py[3] = cy - y;
px[4] = cx + y; py[4] = cy + x;
px[5] = cx - y; py[5] = cy + x;
px[6] = cx + y; py[6] = cy - x;
px[7] = cx - y; py[7] = cy - x;
for (i = 0; i < 8; i++) {
if (px[i] >= 0 && px[i] < SIZE && py[i] >= 0 && py[i] < SIZE) {
grid[py[i]][px[i]] = '*';
}
}
}
int main(void)
{
int r, cx, cy, x, y, d, row, col;
printf("Enter the radius (1-%d): ", (SIZE - 1) / 2);
if (scanf("%d", &r) != 1 || r < 1 || r > (SIZE - 1) / 2) {
printf("Invalid radius.\n");
return 1;
}
memset(grid, ' ', sizeof grid);
cx = SIZE / 2;
cy = SIZE / 2;
/* midpoint circle algorithm: start at the top, walk one octant */
x = 0;
y = r;
d = 1 - r; /* decision variable */
while (x <= y) {
plot(cx, cy, x, y);
if (d < 0) {
d = d + 2 * x + 3; /* midpoint inside: go east */
} else {
d = d + 2 * (x - y) + 5; /* midpoint outside: go southeast */
y--;
}
x++;
}
/* print only the rows the circle touches; double the columns so the
output looks round in a terminal (characters are taller than wide) */
for (row = cy - r; row <= cy + r; row++) {
for (col = cx - r; col <= cx + r; col++) {
printf("%c ", grid[row][col]);
}
printf("\n");
}
return 0;
}
How to Compile and Run
gcc -ansi -Wall -Wextra -o circle circle.c
./circle
Sample Output
Radius 10:
Enter the radius (1-20): 10
* * * * * * *
* * * *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* * * *
* * * * * * *
Radius 3 produces a tidy 7-row circle — try several radii and watch the stepping pattern change.
Code Explanation
plot()— one computed point becomes eight drawn points via the symmetry mirrors. This is the whole reason the algorithm only walks 45° of arc.d = 1 - rand the+3/+5updates — integer-only bookkeeping for “is the true circle inside or outside the midpoint between my two candidate pixels?” Nosqrt, nosin/cos, no rounding errors.printf("%c ", ...)— the extra space doubles each column because terminal characters are roughly twice as tall as wide; without it the circle prints as an egg.memset(grid, ' ', sizeof grid)— a 2-D char canvas is the terminal’s frame buffer; separating “compute the pixels” from “render the canvas” is exactly how real rasterizers are structured.
What About graphics.h?
Honest status: <graphics.h> is the Borland Graphics Interface from Turbo C (1987–1994, MS-DOS). It is not part of any C standard and won’t compile with modern GCC, Clang, or MSVC. If a course still requires it, the practical route is the WinBGIm port bundled with some Windows IDEs — but for real graphics in C today, learn SDL2 or raylib instead; both are free, cross-platform, and actively maintained. The midpoint algorithm above is the same math you’d use to plot pixels in either.
Time and Space Complexity
| Aspect | Complexity | Why |
|---|---|---|
| Time | O(r) | ~r/√2 loop iterations, 8 plots each |
| Space | O(SIZE²) | the character canvas |
| Arithmetic | integer only | adds and comparisons — no floating point at all |
What This Program Teaches
- The midpoint/Bresenham technique: replacing geometry with an incremental integer decision variable
- 8-way symmetry — compute once, mirror everywhere
- Separating computation (plot into a buffer) from presentation (render the buffer)
- The real story of
graphics.h, and what to use instead in 2026
Related C Programs
- Pascal’s Triangle in C — more formatted 2-D console output
- Floyd’s Triangle in C
- cos(x) in C — Taylor Series — the trigonometric route this algorithm avoids
- Debug C Programs with GDB — step through the decision variable and watch it work
Test yourself: our free C Programming Quiz app for Android has 150+ questions with explanations for every answer.
Recommended Book
The C Programming Language by Kernighan & Ritchie remains the definitive C reference — we’ve solved all of its exercises. Also on Amazon.com.