A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
C converts types silently in dozens of contexts. Assign a double to an int and the fractional part vanishes. Pass a char to a function expecting int and it widens without complaint. Mix signed and unsigned in an expression and the signed value becomes unsigned, which means -1 becomes the largest possible unsigned value. These implicit conversions are legal, they compile without error, and they are responsible for a staggering number of production bugs.
#include <stdio.h>int main(void) {int whole = 7;double decimal = whole;printf("Widening: int %d -> double %.1f\n", whole, decimal);double pi = 3.14159;int truncated = pi;printf("Narrowing: double %.5f -> int %d\n", pi, truncated);float f = 1e10f;int overflow = f;printf("Overflow: float %.0f -> int %d\n", f, overflow);return 0;}
The narrowing from double to int truncates toward zero. It does not round. 3.99 becomes 3, not 4. The float-to-int overflow case is undefined behavior. On this platform it saturated to INT_MAX, but the standard does not guarantee that. With -Wconversion, GCC warns on the narrowing assignments. Without it, silence.
An explicit cast is (type)expression. It tells the compiler and the reader: I know this conversion loses information or changes semantics, and I accept responsibility. The most common legitimate use: casting the result of integer division to double when you need a fractional answer.
#include <stdio.h>int main(void) {int a = 7;int b = 2;int int_result = a / b;double bad_cast = a / b;double good_cast = (double)a / b;printf("Integer division: %d\n", int_result);printf("Cast after division: %.2f\n", bad_cast);printf("Cast before division: %.2f\n", good_cast);return 0;}
The bad_cast line is the classic mistake. a / b is evaluated as integer division first, producing 3. Then 3 is converted to double, giving 3.00. The cast on the result does not recover the lost fractional part. You must cast one operand before the division happens.
#include <stdio.h>int main(void) {int signed_val = -1;unsigned int unsigned_val = 1;if (signed_val < unsigned_val) {printf("-1 is less than 1\n");} else {printf("-1 is NOT less than 1 (what?)\n");}printf("signed_val as unsigned: %u\n", (unsigned int)signed_val);return 0;}
When signed and unsigned meet in an expression, the signed value is converted to unsigned. -1 becomes UINT_MAX (4294967295). The comparison then evaluates 4294967295 < 1, which is false. This is not a compiler bug. It is the standard's usual arithmetic conversions. It has caused security vulnerabilities in bounds checks where a negative length was compared against an unsigned buffer size.
Type conversion in C is a minefield with a simple map: widening is safe, narrowing loses data, and mixing signed with unsigned is where the truly surprising bugs live. Compile with -Wconversion. Read every warning. Next: constants, which lock values in place and interact with the preprocessor in ways that matter.
Finish the lesson once you have worked through the material. This awards ★ 20 XP.