Exercise 1-1. Run the “hello, world” program on your system. Experiment with leaving out parts of the program to see what error messages you get.
This page covers the printf side of Exercise 1-1: what the format string actually does, how escape sequences work, and what happens when you modify or multiply printf calls. For the compiler-error experiments — missing semicolons, missing braces, missing #include — see Exercise 1-1a.
How printf Actually Works
printf writes characters to standard output (stdout). Its first argument is the format string: a sequence of ordinary characters that pass straight through to the output, plus escape sequences that begin with a backslash. The most important escape sequence in Chapter 1 is \n, which inserts a newline character. Without it, the cursor stays on the same line as your shell prompt — a confusing sight the first time you see it.
Everything printf writes goes into a buffer before it reaches the screen. On most systems that buffer flushes automatically when the program exits cleanly, or when a \n is written to a terminal. That is why the original hello-world program displays correctly even though there is no explicit flush call.
Variation 1 — The Original Program
/* Compile: gcc -ansi -Wall ex1-1b.c -o ex1-1b */
#include <stdio.h>
int main(void)
{
printf("hello, world\n");
return 0;
}
Output
hello, world
The \n at the end of the string moves the cursor to a new line after the message. That one character makes the difference between clean output and a terminal that looks garbled.
Variation 2 — Change the Message
The simplest experiment is to replace the string literal. printf does not care what text you give it — it copies each character to stdout in order. Swap the message for anything you like.
/* Compile: gcc -ansi -Wall ex1-1b.c -o ex1-1b */
#include <stdio.h>
int main(void)
{
printf("goodbye, world\n");
return 0;
}
Output
goodbye, world
Variation 3 — Two printf Calls, One Output Line
A single printf call is not required to produce a complete line. Two consecutive calls with no \n between them run their output together on the same line. Only the newline in the second call terminates the line.
/* Compile: gcc -ansi -Wall ex1-1b.c -o ex1-1b */
#include <stdio.h>
int main(void)
{
printf("hello, ");
printf("world\n");
return 0;
}
Output
hello, world
The output is identical to Variation 1. This shows that a line of output is not tied to a single function call. printf simply appends bytes to the output stream; the boundary between calls is invisible in the result.
Variation 4 — One printf, Two Lines
You can embed multiple \n sequences in a single format string to produce multiple lines of output from one call. There is no limit on how many escape sequences a single string can contain.
/* Compile: gcc -ansi -Wall ex1-1b.c -o ex1-1b */
#include <stdio.h>
int main(void)
{
printf("hello, world\ngoodbye, world\n");
return 0;
}
Output
hello, world goodbye, world
Variation 5 — No Newline at the End
Drop the trailing \n and the text is still written to stdout, but no newline is emitted. On a terminal the shell prompt appears immediately after the text on the same line. This looks broken, but it is technically correct: the output is just missing a line terminator.
/* Compile: gcc -ansi -Wall ex1-1b.c -o ex1-1b */
#include <stdio.h>
int main(void)
{
printf("hello, world");
return 0;
}
Output (terminal — $ represents the shell prompt)
hello, world$
The prompt runs straight on after the text. Always end your output with \n unless you have a deliberate reason not to — it keeps the terminal usable and is considered correct behaviour by POSIX.
Variation 6 — Printing a Number with %d
The format string is more than a plain text template. The %d conversion specifier tells printf to read the next argument and insert it as a decimal integer. This is your first look at printf’s real power: mixed text and data in one call.
/* Compile: gcc -ansi -Wall ex1-1b.c -o ex1-1b */
#include <stdio.h>
int main(void)
{
printf("The answer is %d\n", 42);
return 0;
}
Output
The answer is 42
K&R uses %d throughout Chapter 1. You will see it again in the temperature-conversion table (Exercise 1-3) and the Fahrenheit-Celsius table (Exercise 1-4). Getting comfortable with it now pays off immediately.
Compile and Run
gcc -ansi -Wall ex1-1b.c -o ex1-1b
./ex1-1b
The -ansi flag enforces the original C89 standard — the dialect K&R 2nd edition was written for. The -Wall flag enables all common warnings. Build this habit early: warnings often reveal real bugs.
What This Exercise Teaches
- printf format strings — the first argument is a template, not just a message. Ordinary characters pass through unchanged; sequences beginning with
%or\have special meaning and are processed before output. - Escape sequences —
\n(newline),\t(tab),\\(literal backslash), and others allow you to embed control characters in a string literal. The backslash itself is never printed. - stdout buffering — printf writes to a buffer, not directly to the screen. On terminals the buffer typically flushes on each
\n; omitting the newline can delay output or cause the prompt to appear mid-line. - Output stream vs. function call — multiple printf calls write to the same sequential stream. There is no implied separator between calls; the stream is simply a flow of bytes and you control every character in it.
Set Up Your C Environment
Need to get GCC running before you can try these examples? Start here:
- Complete C Development Environment Setup — the full guide if you are brand new to C
- Install GCC on Windows 11
- Install GCC on macOS
- Install GCC on Ubuntu/Linux
- VS Code for C Programming — recommended editor
- Best Online C Compilers — run C in the browser, no install needed
← Exercise 1-1a |
Chapter 1 Solutions |
Exercise 1-1c →
Book:
The C Programming Language, 2nd Ed — Kernighan & Ritchie