Skip to content
Numbers and printf
step 1/5

Reading — step 1 of 5

Learn

~3 min readGetting Started

Numbers and printf

C's arithmetic is the template every language in this catalog copied — including the sharp corners. The two that matter daily: integer division truncates, and printf's format specifiers are a type contract the compiler barely checks. Master both here, on a rectangle, before they matter on a kernel.

Integer vs floating arithmetic

7 / 2        /* 3   — int ÷ int stays int, truncated toward zero */
7 % 2        /* 1   — remainder */
7.0 / 2      /* 3.5 — one double infects the expression upward */
99 / 100     /* 0   — the percentage-is-always-zero classic */

Division's type is decided by its operands, not its destination: double d = 7 / 2; stores 3.0 — the division already happened in integer land before the assignment looked at it. The fix is a cast on an operand: double d = (double)a / b;. This single line — cast then divide — is the difference between right and wrong in every averaging computation you'll ever write in C.

% gets the usual jobs (divisibility n % 3 == 0, wraparound, digit-peeling with n % 10 / n / 10) and one C-specific footnote: it's integer-only — floating remainder is fmod() from <math.h>.

Overflow, stated plainly because C is unique here: unsigned overflow wraps (defined), signed overflow is undefined behavior — the compiler may assume it can't happen and optimize accordingly, producing genuinely arbitrary results. With int topping out at ~2.1 billion, products of big inputs need long long before the multiply, not after.

printf: the specifier contract

Each % specifier promises "an argument of this type comes next," and C trusts you:

printf("%d\n", 42);            /* int */
printf("%lld\n", big);         /* long long */
printf("%f\n", 3.14159);       /* double → 3.141590 (6 decimals default) */
printf("%.2f\n", 3.14159);     /* 3.14 — rounds, doesn't truncate */
printf("%c %s\n", 'A', "hi");  /* char, string */
printf("%6d|%-6d|%06d\n", 42, 42, 42);   /*     42|42    |000042 */

Width and precision compose like you'd hope: %8.2f is "8 columns, 2 decimals." The one to engrave: %.2f — graded output demands exact decimal places constantly, and %f's six-decimal default (15.000000) fails a grader expecting 15.00.

Mismatch a specifier and the type (%d with a double) and you get undefined behavior — usually garbage output, occasionally a crash, never an error message at the point of sin. gcc -Wall diagnoses most of these at compile time; this is the single best argument for warnings-as-mandatory.

The math library

#include <math.h>
sqrt(2.0)      /* 1.414214 */
pow(2, 10)     /* 1024.0 — returns double, always */
fabs(-3.5)     /* 3.5 — fabs for floating, abs (stdlib.h) for int */

Historical quirk with modern consequences: on many toolchains, using <math.h> requires linking the math library — gcc -o prog prog.c -lm. The grader handles this; your future laptop sessions will thank you for knowing why undefined reference to sqrt happens.

Your exercise: Rectangle Area

Read the two integer dimensions — the starter's scanf("%d", ...) lines already do that — multiply, and print with printf("%d\n", w * h);. Input 5 then 3 must print exactly 15. The grader catches: a missing \n, the type-contract violation of printing an int with %f (garbage output), and any extra text — Area: 15 fails, bare 15 passes. One multiplication; the grade rides entirely on the type contract around it — which is C in miniature.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…