In Lesson 10 of Learn C With Me, we continue our exploration of File Input/Output in C, this time moving from text files to binary files.
Using Beej's Guide to C, we learn how binary streams work, how to read and write raw data with fread() and fwrite(), and why writing binary data directly from memory introduces some important portability problems.
We cover:
- Binary files and binary streams
- The difference between text and binary I/O
- Opening files with
"rb" and "wb"
- Reading binary data with
fread()
- Writing binary data with
fwrite()
- Understanding the arguments to
fread() and fwrite()
- Writing arrays of bytes to a file
- Reading binary data back into memory
- Inspecting binary files with
hexdump
- Working with
unsigned char and raw bytes
- Writing values larger than one byte
- Byte order and endianness
- Why multibyte values can be stored differently on different architectures
- Why directly writing a
struct to disk isn't portable
- Struct padding
- Why compiler and architecture differences matter
- The idea of serialization
- Why portable binary formats need a defined representation
- A brief look at Protocol Buffers
- Why serialization allows data to move between architectures and programming languages
One of the biggest takeaways from this lesson is that binary data is just bytes. Writing a simple array of bytes is straightforward, but things become more complicated once we start writing multibyte integers or complete structs directly from memory.
We experiment with this ourselves and run into endianness, where the same multibyte value can have a different byte order depending on the architecture. We also revisit structs and see why compiler-added padding makes dumping an entire struct directly to a file non-portable.
This leads us to serialization: instead of blindly copying memory to disk, we define exactly how our data should be represented. We briefly look at Google's Protocol Buffers as a real-world example of a serialization system.
As usual, we experiment, make predictions, get things wrong, inspect the actual bytes, get help from the live chat, and try to understand what C is actually doing under the hood.
With this stream, we finish Chapter 9 — File Input/Output. Next time, we move on to a new topic.
This is an interactive, follow-along live course. I am learning C alongside you, so expect questions, mistakes, experiments and plenty of discussion. No passive watching here — participate in the chat and work through the examples with us.
00:00:00 Starting the stream
00:12:07 Binary File I/O
00:13:24 Opening binary files — rb and wb
00:14:17 fread() and fwrite()
00:23:14 Writing binary data
00:24:27 Our first fwrite() example
00:34:15 Inspecting the binary file
00:38:46 Reading binary data back with fread()
00:55:57 Structs, padding & portability
00:59:32 Writing multibyte values
01:16:18 Byte order & endianness
01:21:41 Serialization
01:23:30 Protocol Buffers
01:31:19 Wrapping up File I/O
01:32:21 Homework discussion
01:38:46 Lesson finished & post-stream chat
This is an interactive, follow-along live course. I am learning C alongside you, so expect questions, mistakes, experiments and plenty of discussion. No passive watching here — participate in the chat and work through the examples with us.
📅 We go live every Sunday at 19:00 CEST — interactive, follow-along C programming sessions.
📖 Study material:
Beej's Guide to C
📚 Course materials:
Linux Renaissance C Programming Course
💬 Homework & discussion:
Linux Renaissance Forum
📺 All C Programming lessons:
C Programming playlist
🔴 This stream is proudly sponsored by OPNsense — the open source firewall and routing platform trusted by professionals worldwide.
OPNsense
Support Linux Renaissance
🛒 Shop: Linux Renaissance Shop
☕ Ko-fi: Ko-fi
🎖️ Patreon: Patreon
▶️ YouTube membership: YouTube Membership
Find me elsewhere
🌐 Blog: Linux Renaissance
🎥 PeerTube: Linux Renaissance on PeerTube
📺 Odysee: Linux Renaissance on Odysee
🎮 Twitch: Linux Renaissance on Twitch
💬 Matrix: Linux Renaissance Matrix space