HOWTO · C

How to Align Columns in printf Function in C

Learn how to align C output with printf field widths, dynamic widths, and zero-padded integers.

On this page

Use a printf field width to align columns in C. %10d right-aligns an integer in a field at least 10 characters wide; %*d takes that width from an argument, and %0*d pads an integer with leading zeroes. Use %-*s or the - flag to left-align text in a table.

Use a field width to align output in C

A field width sets the minimum number of characters used for a value. For an integer, %10d right-aligns the value and pads on the left with spaces when it takes fewer than 10 characters. A wider value is printed in full, so the width does not truncate it. This is useful when the final characters in a column should line up; shorter values start farther to the right because the conversion is right-aligned.

This complete example shows the right-aligned values beside a visible separator:

#include <stdio.h>

int main(void) {
  int values[] = {11011, 111, 11};

  for (int i = 0; i < 3; ++i) {
    printf("%10d | %d\n", values[i], values[i]);
  }

  return 0;
}
     11011 | 11011
       111 | 111
        11 | 11

The first conversion reserves a minimum width of 10; the second uses the value’s natural width. The | character makes the field boundary visible. In general, the number in a format such as %10d is the total minimum field width, not a count of spaces to add.

Use %*d for a dynamic field width

Use %*d when the field width is known only while the program runs. Each * in a conversion consumes an int argument immediately before the value for that conversion. For example, in printf("%*d", width, value), width supplies the field width and value supplies the integer.

This complete example sets a width at runtime and passes it immediately before each integer value:

#include <stdio.h>

int main(void) {
  int width = 10;
  int values[] = {11011, 111, 11};

  for (int i = 0; i < 3; ++i) {
    printf("%*d | %d\n", width, values[i], values[i]);
  }

  return 0;
}
     11011 | 11011
       111 | 111
        11 | 11

The first conversion uses the value of width as its minimum field width, so shorter integers receive leading spaces and wider values remain intact. The second conversion prints the same integer at its natural width.

The - flag left-aligns the value. It can be combined with a dynamic width as %-*d; the width argument remains before the value argument. For example, printf("%*d | %-*d\n", width, value, width, value) uses width before each corresponding integer. The first field is right-aligned by default, and the second is left-aligned. Pass a different width before a value when the layout changes by row.

Combine field widths to align table columns

For a mixed table, give text and number fields widths that fit the intended columns. The - flag left-aligns labels, while integer conversions without it right-align numbers. A | separator distinguishes the columns. With %*.*d, the first * consumes the width, the second consumes the precision, and the final argument is the integer value. Integer precision sets a minimum number of digits, adding leading zeroes as needed.

This complete table example uses fixed-width columns for the headings and sample rows:

#include <stdio.h>

int main(void) {
  int width = 12;

  printf("%-*s | %-*s | %*s\n", width, "Number", width,
         "Description", width, "Value");
  printf("%-*d | %-*s | %*.*d\n", width, 123, width, "First",
         width, 4, 4567);
  printf("%-*d | %-*s | %*.*d\n", width, 456, width, "Second",
         width, 4, 789);

  return 0;
}
Number       | Description  |        Value
123          | First        |         4567
456          | Second       |         0789

The number and description columns are left-aligned here to make the row layout easy to scan; remove - from an integer conversion to right-align that number instead. Each width or precision supplied with * must have a matching int argument in the same order. Terminal display width can differ for text containing multibyte or wide characters, so these byte-oriented examples use ordinary ASCII text.

Use %0*d for zero-padded integers

Use %0*d when an integer should have a minimum width filled with leading zeroes. The * consumes the width argument before the integer. Unlike space padding from %*d, zero padding keeps numeric identifiers and counts at a consistent digit width.

This complete example prints two integers with a minimum width of five digits:

#include <stdio.h>

int main(void) {
  int width = 5;

  printf("%0*d\n", width, 123);
  printf("%0*d\n", width, 7);

  return 0;
}
00123
00007

The width is a minimum, so a value with more digits than the chosen width is still printed in full. For a table, apply the same numeric width to each row; use space-padded fields for headings or text.

Conclusion

Choose %10d or another fixed field width when the layout is known. Use %*d when the width comes from a variable, and add - when a field should be left-aligned. Use %0*d for numeric identifiers or counts that need leading zeroes. These format choices make ordinary ASCII console output easier to scan, while the terminal’s display width can affect alignment for other text.