C Notes
Complete reference guide for all format specifiers in C: %d, %f, %c, %s, %p, %x, %o, %u, %e, %g, and more. Covers width, precision, length modifiers, and scanf vs printf differences.
Format specifiers are the backbone of C's input/output system. They tell printf() how to display data and scanf() how to interpret input. Every time you use %d, %f, or %s, you're using a format specifier. This guide serves as a complete reference for all format specifiers available in C, along with their modifiers and practical usage.
General Format Specifier Syntax
Each component is optional except the % and the specifier character itself.
Complete List of Format Specifiers
Integer Specifiers
| Specifier | Description | Example Input | Example Output |
|---|---|---|---|
%d | Signed decimal integer | 42 | 42 |
%i | Signed integer (auto-detects base in scanf) | 0x1A | 26 |
%u | Unsigned decimal integer | 42 | 42 |
%o | Unsigned octal | 42 | 52 |
%x | Unsigned hex (lowercase) | 255 | ff |
%X | Unsigned hex (uppercase) | 255 | FF |
Floating-Point Specifiers
| Specifier | Description | Example Input | Example Output |
|---|---|---|---|
%f | Decimal floating-point | 3.14 | 3.140000 |
%e | Scientific notation (lowercase) | 3.14 | 3.140000e+00 |
%E | Scientific notation (uppercase) | 3.14 | 3.140000E+00 |
%g | Shorter of %f or %e | 3.14 | 3.14 |
%G | Shorter of %f or %E | 0.00001 | 1E-05 |
%a | Hexadecimal floating-point | 3.14 | 0x1.91eb86p+1 |
Character and String Specifiers
| Specifier | Description | Example Output |
|---|---|---|
%c | Single character | A |
%s | String (null-terminated) | Hello |
Other Specifiers
| Specifier | Description | Example Output |
|---|---|---|
%p | Pointer address | 0x7ffd4a3b |
%n | Stores count of chars written so far | (no output) |
%% | Literal percent sign | % |
Demonstrating All Specifiers
#include <stdio.h>
int main() {
int num = 255;
float fnum = 3.14159;
double dnum = 2.718281828;
char ch = 'A';
char str[] = "Hello";
int *ptr = #
printf("=== Integer Specifiers ===\n");
printf("%%d: %d\n", num);
printf("%%i: %i\n", num);
printf("%%u: %u\n", (unsigned)num);
printf("%%o: %o\n", num);
printf("%%x: %x\n", num);
printf("%%X: %X\n", num);
printf("\n=== Float Specifiers ===\n");
printf("%%f: %f\n", fnum);
printf("%%e: %e\n", fnum);
printf("%%E: %E\n", fnum);
printf("%%g: %g\n", fnum);
printf("%%G: %G\n", fnum);
printf("\n=== Other Specifiers ===\n");
printf("%%c: %c\n", ch);
printf("%%s: %s\n", str);
printf("%%p: %p\n", (void*)ptr);
printf("%%%%: %%\n");
return 0;
}=== Integer Specifiers === %d: 255 %i: 255 %u: 255 %o: 377 %x: ff %X: FF === Float Specifiers === %f: 3.141590 %e: 3.141590e+00 %E: 3.141590E+00 %g: 3.14159 %G: 3.14159 === Other Specifiers === %c: A %s: Hello %p: 0x7ffd5e8a3c4c %%: %
Length Modifiers
Length modifiers specify the exact size of the argument:
| Modifier | With %d | With %u/%x/%o | With %f | With %c/%s |
|---|---|---|---|---|
hh | signed char | unsigned char | — | — |
h | short | unsigned short | — | — |
| (none) | int | unsigned int | double* | char/char* |
l | long | unsigned long | double | wchar_t/wchar_t* |
ll | long long | unsigned long long | — | — |
L | — | — | long double | — |
z | size_t | size_t | — | — |
*Note: In printf, float is promoted to double, so %f always takes double.
#include <stdio.h>
int main() {
short s = 32767;
long l = 2147483647L;
long long ll = 9223372036854775807LL;
unsigned long ul = 4294967295UL;
long double ld = 3.14159265358979323846L;
size_t sz = sizeof(int);
printf("short: %hd\n", s);
printf("long: %ld\n", l);
printf("long long: %lld\n", ll);
printf("ulong: %lu\n", ul);
printf("long double: %Lf\n", ld);
printf("size_t: %zu\n", sz);
return 0;
}short: 32767 long: 2147483647 long long: 9223372036854775807 ulong: 4294967295 long double: 3.141593 size_t: 4
Width and Precision Reference
Width Examples
[42] [ 42] [42 ] [00042] [ 42] [Hi] [ Hi] [Hi ]
Precision Examples
3 3.14 3.14159 3.1415926536 00042 00000042 Hello Hel 3.142 [ 3.142] [3.142 ]
Flags Reference
| Flag | Effect | Example | Output |
|---|---|---|---|
- | Left-align | %-10d, 42 | [42 ] |
+ | Show sign for positive | %+d, 42 | +42 |
| Space for positive | % d, 42 | 42 |
0 | Zero-pad | %05d, 42 | 00042 |
# | Alternate form | %#x, 255 | 0xff |
[ +42] [+42 ] [+000000042] [ 42] Dec: 255 Oct: 0377 Hex: 0xff HEX: 0XFF 3 vs 3.
scanf() vs printf() Differences
| Aspect | printf() | scanf() |
|---|---|---|
| float | %f (works for float AND double) | %f (float only!) |
| double | %f or %lf | %lf (MUST use!) |
%i | Same as %d | Auto-detects base (dec/oct/hex) |
| strings | Prints until \0 | Reads until whitespace |
& needed? | No (passes by value) | Yes (needs address) |
#include <stdio.h>
int main() {
// Demonstration of %i in scanf vs printf
int num;
// In scanf, %i auto-detects base:
// "42" → decimal 42
// "052" → octal 42
// "0x2A" → hex 42
printf("Enter a number (try 0x1F or 031): ");
scanf("%i", &num);
printf("Value in decimal: %d\n", num);
printf("Value in hex: %x\n", num);
printf("Value in octal: %o\n", num);
return 0;
}Enter a number (try 0x1F or 031): 0x1F Value in decimal: 31 Value in hex: 1f Value in octal: 37
Practical Formatting Recipes
Currency Formatting
#include <stdio.h>
int main() {
double price = 1234.5;
printf("Price: $%,.2f\n", price); // Note: , flag is not standard C
printf("Price: $%.2f\n", price); // Standard way
printf("Price: $%10.2f\n", price); // Right-aligned in field
return 0;
}Price: $1234.50 Price: $1234.50 Price: $ 1234.50
Printing Binary (Custom)
#include <stdio.h>
void printBinary(unsigned int n) {
for (int i = 31; i >= 0; i--) {
printf("%d", (n >> i) & 1);
if (i % 8 == 0) printf(" ");
}
printf("\n");
}
int main() {
printf("42 in binary: ");
printBinary(42);
printf("255 in binary: ");
printBinary(255);
return 0;
}42 in binary: 00000000 00000000 00000000 00101010 255 in binary: 00000000 00000000 00000000 11111111
Memory Size Display
#include <stdio.h>
int main() {
printf("%-15s %s\n", "Type", "Size (bytes)");
printf("%-15s %s\n", "----", "------------");
printf("%-15s %zu\n", "char", sizeof(char));
printf("%-15s %zu\n", "short", sizeof(short));
printf("%-15s %zu\n", "int", sizeof(int));
printf("%-15s %zu\n", "long", sizeof(long));
printf("%-15s %zu\n", "long long", sizeof(long long));
printf("%-15s %zu\n", "float", sizeof(float));
printf("%-15s %zu\n", "double", sizeof(double));
printf("%-15s %zu\n", "long double", sizeof(long double));
printf("%-15s %zu\n", "pointer", sizeof(void*));
return 0;
}Type Size (bytes) ---- ------------ char 1 short 2 int 4 long 4 long long 8 float 4 double 8 long double 16 pointer 8
Interview Questions
Q1: What is the difference between %d and %i in scanf()?
In printf(), they're identical. In scanf(), %d reads only decimal integers, while %i auto-detects the base: if input starts with 0x, it reads hexadecimal; if it starts with 0, it reads octal; otherwise decimal. For example, scanf("%i", &n) with input 010 gives n = 8 (octal), while scanf("%d", &n) gives n = 10 (decimal).
Q2: What happens if you use %f for a double in scanf()?
It's undefined behavior. %f in scanf expects a float* (4 bytes), but a double occupies 8 bytes. Only 4 bytes get written correctly, potentially corrupting adjacent memory. Always use %lf for double in scanf.
Q3: How do you print a pointer address in C?
Use %p with a cast to void*: printf("%p", (void*)ptr). The output format is implementation-defined but typically shows a hexadecimal address. The cast to void* is technically required for portability.
**Q4: What does the * mean in %*d for printf vs scanf?**
In printf(), %*d means the width is supplied as an argument: printf("%*d", 10, 42) prints 42 in a width of 10. In scanf(), %*d means "read and discard" — it reads an integer from input but doesn't store it anywhere (suppresses assignment).
Q5: How do you use %n and why is it considered dangerous?
%n stores the count of characters written so far into an integer variable: printf("Hello%n", &count) sets count to 5. It's dangerous because in format string attacks, malicious input could use %n to write to arbitrary memory locations. Many systems disable it for security.
Summary
- Format specifiers control how data is read and displayed in C I/O functions
- The full syntax is
%[flags][width][.precision][length]specifier - Integer types:
%d,%u,%o,%x; Float types:%f,%e,%g - Length modifiers (
h,l,ll,L,z) specify exact variable size - Precision means different things: decimal places for floats, minimum digits for ints, max chars for strings
- Critical difference: use
%lffor double in scanf but%fworks in printf - Always match specifiers to types — mismatches cause undefined behavior
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Format Specifiers in C - Complete Reference.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this C Programming topic.
Search Terms
c-programming, c programming, programming, input, output, format, specifiers, format specifiers in c - complete reference
Related C Programming Topics