5.1.21 · D1C Programming

Foundations — Safe alternatives — strncpy, snprintf, strlcpy

1,463 words7 min readBack to topic

Before you can understand strncpy, snprintf, or strlcpy, you must be able to see what a C string actually is in memory. The parent note throws around char buf[8], '\0', sizeof, size, and "off the end" as if they were obvious. This page earns every one of those, in order, from nothing.


1. A byte, a char, and a box of boxes

The picture you must hold in your head for the entire topic: memory is a long strip of numbered boxes, and each box holds one number that we can read as a letter.

Figure — Safe alternatives — strncpy, snprintf, strlcpy

2. char buf[8] — a fixed row of 8 boxes

Figure — Safe alternatives — strncpy, snprintf, strlcpy

Notice there is nothing built into buf that says "I am 8 long." The number 8 lives only in your source code, not in memory. This missing length is the reason C string functions are dangerous — see C strings and the null terminator.


3. '\0' — the null terminator (the "end" marker)

This is the single most important symbol in the whole topic. A "string" in C is defined as:

Figure — Safe alternatives — strncpy, snprintf, strlcpy

4. sizeof vs the content length — two different numbers


5. Pointers, size_t, and the dest/src names


6. Putting it together: what "overflow" looks like

Figure — Safe alternatives — strncpy, snprintf, strlcpy

Now the parent note's opening example reads itself:

char buf[8];
strcpy(buf, "hello world");   // 12 chars → needs 13 boxes

"hello world" needs boxes, but buf has only 8. strcpy doesn't know or check sizeof(buf), so it keeps writing past box 7 into boxes 8, 9, 10… that belong to other things — the essence of Buffer overflow and stack smashing and Memory safety and undefined behavior.


Prerequisite map

Byte equals one char box

char buf 8 is a row of boxes

Null terminator marks the end

A C string is boxes plus marker

sizeof is capacity

strlen is content length

strlen must be at most sizeof minus 1

Overflow walks off the row

Safe alternatives strncpy snprintf strlcpy


Equipment checklist

How many boxes does char buf[8] reserve, and what is the last legal index?
8 boxes; the last legal index is buf[7] (indexing starts at 0).
What number is stored in the '\0' byte, and how is it different from '0'?
'\0' stores 0; '0' stores 48 — they are completely different bytes.
Why does storing k visible characters require k+1 boxes?
One extra box is needed for the '\0' end-marker.
What does sizeof(buf) measure versus strlen(buf)?
sizeof = total capacity in bytes (compile-time); strlen = visible characters up to the '\0' (walked at run time).
State the safety inequality relating content to capacity.
strlen(buf) <= sizeof(buf) - 1.
How does a string function "know" where a string ends if C stores no length?
It walks forward from box 0 until it finds a '\0' byte.
In copy(dest, src, size), which side can overflow and why?
dest — it may be too small to hold what src pours in.
Give the one-line rule that detects truncation.
Truncation happened iff return >= size.

Connections

  • Parent: Safe alternatives
  • C strings and the null terminator
  • sizeof vs strlen
  • strcpy and sprintf (unsafe)
  • Buffer overflow and stack smashing
  • Memory safety and undefined behavior
  • Format strings and printf family