A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
C has no string type. What it has is a convention: a sequence of char values terminated by a zero byte. That is the entire abstraction. Every string function in the standard library walks memory from the start until it hits \0. If that terminator is missing, the function keeps walking. Into the next variable. Into the next stack frame. Into unmapped memory. Until it segfaults or, worse, silently reads data it should not.
#include <stdio.h>#include <string.h>int main(void) {char stack_str[] = "Hello";char *literal_str = "World";printf("stack_str: %s (len=%zu)\n", stack_str, strlen(stack_str));printf("literal_str: %s (len=%zu)\n", literal_str, strlen(literal_str));stack_str[0] = 'h';printf("Modified: %s\n", stack_str);return 0;}
stack_str is a mutable array on the stack. You can modify its characters. literal_str points to a string literal stored in read-only memory. Attempting literal_str[0] = 'w' is undefined behavior and will segfault on most platforms. The distinction between a char array and a pointer to a string literal is one of the most tested interview questions in C, and we dedicate a full lesson to it later.
#include <stdio.h>#include <string.h>int main(void) {char buf[6];buf[0] = 'H';buf[1] = 'i';buf[2] = '\0';printf("With terminator: '%s' (len=%zu)\n", buf, strlen(buf));buf[2] = '!';buf[3] = '!';buf[4] = '!';buf[5] = '!';printf("Without terminator: '%s'\n", buf);return 0;}
Once I removed the null terminator, printf kept reading past the buffer until it found a zero byte somewhere in adjacent stack memory. The output includes garbage bytes. In a security context, this is an information leak. The function is reading memory it was never meant to expose. This exact class of bug has been assigned CVEs in production software.
Every time you manually construct a string character by character, you must explicitly place the null terminator. Forgetting it is not a style issue. It is a memory safety violation. Use snprintf or strncpy (with manual termination) rather than building strings by hand whenever possible.
strlen("Hello") returns 5. The buffer holding that string literal is 6 bytes: five characters plus the null. strlen counts characters up to but not including \0. sizeof("Hello") returns 6 because sizeof includes the terminator. Mixing these up when allocating buffers leads to off-by-one overflows. Allocate strlen(s) + 1 bytes when copying a string.
Strings in C are a convention enforced by discipline, not by the type system. The standard library provides dozens of functions for manipulating them, and we spend an entire module on those functions later. For now, internalize this: a C string is a char pointer that promises a zero byte exists somewhere ahead. Break that promise and everything downstream fails. Next module: the type system, starting with type casting.
Finish the lesson once you have worked through the material. This awards ★ 20 XP.