Strings in C
Strings are character arrays ending with \0. Learn to create strings, read them safely, and use string functions like strlen, strcpy, strcmp.
What You Will Learn
- ✓Understand strings as char arrays with \0
- ✓Create and initialize strings
- ✓Read strings safely with fgets (not gets!)
- ✓Use string functions: strlen, strcpy, strcmp
01What is a String?
In C, a string is simply an array of characters that ends with a special character called the null terminator ('\0').
🔤 String = Character Array + Null Terminator
Unlike some languages where strings are a built-in type, C doesn't have a dedicated string type. Instead, strings are arrays of char.
The string "Hello" is stored as 6 characters (5 letters + null terminator)
Why the Null Terminator?
The \0 character tells functions like printf()where the string ends. Without it, functions would keep reading random memory until they crash!
02Declaring Strings
There are several ways to create strings in C:
📝 This program shows 4 different ways to declare strings and prints each one. Note the difference between arrays and pointers!
1#include <stdio.h>23int main() {4 // Method 1: Character array with size5 char name[10] = "Alice"; // Allocates 10 bytes, uses 6 (5+\0)6 7 // Method 2: Let compiler determine size8 char greeting[] = "Hello"; // Compiler allocates 6 bytes9 10 // Method 3: Character by character (must add \0!)11 char word[4] = {'C', 'a', 't', '\0'};12 13 // Method 4: Pointer to string literal (read-only!)14 char *message = "World";15 16 // Print all strings17 printf("Name: %s\n", name);18 printf("Greeting: %s\n", greeting);19 printf("Word: %s\n", word);20 printf("Message: %s\n", message);21 22 return 0;23}🔍 How This Program Works
char name[10] = "Alice" — Allocates 10 bytes, stores "Alice" + \0 (6 bytes used, 4 empty).
char greeting[] = "Hello" — Compiler counts and allocates exactly 6 bytes (5 chars + null terminator).
{'C', 'a', 't', '\\0'} — Manual char-by-char. You must add \0 or string functions will fail!
char *message = "World" — Pointer to a string literal stored in read-only memory. Cannot modify!
%s format specifier — Prints characters until it finds \0. That's why null terminator is essential!
char name[] = "Alice";
- • Creates a modifiable character array
- • You can change individual characters
- • Stored in stack memory
char *name = "Alice";
- • Pointer to a read-only string literal
- • Cannot modify characters!
- • String stored in read-only memory
⚠️ Common Mistake
char *str = "Hello";str[0] = 'J'; // CRASH! String literals are read-onlychar str2[] = "Hello";str2[0] = 'J'; // OK! This is a modifiable array03String Memory Layout
Understanding how strings are stored in memory is crucial for avoiding bugs.
char str[10] = "Hello";
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
Used (5 chars)
H, e, l, l, o
Null terminator
\0 (ASCII 0)
Unused space
Contains garbage
String Size Calculation
Array size needed = string length + 1 (for \0)
For "Hello": 5 characters + 1 null = 6 bytes minimum
📝 This program demonstrates the difference between sizeof() and strlen(), and prints the memory address of each character in the string.
1#include <stdio.h>2#include <string.h> // For strlen()34int main() {5 char str[] = "Hello";6 7 // sizeof() returns total array size (including \0)8 printf("sizeof(str): %zu bytes\n", sizeof(str)); // 69 10 // strlen() returns string length (excluding \0)11 printf("strlen(str): %zu characters\n", strlen(str)); // 512 13 // Show address of each character14 printf("\n--- Address Calculation for \"%s\" ---\n", str);15 printf("Base Address: %p\n\n", (void*)str);16 printf("Index | Char | Address | Calculation\n");17 printf("----------------------------------------------\n");18 for (int i = 0; i <= strlen(str); i++) {19 if (str[i] == '\0') {20 printf(" %d | \\0 | %p | Base + %d\n", 21 i, (void*)&str[i], i);22 } else {23 printf(" %d | '%c' | %p | Base + %d\n", 24 i, str[i], (void*)&str[i], i);25 }26 }27 printf("----------------------------------------------\n");28 29 // Important difference!30 char buffer[100] = "Hi";31 printf("\nsizeof(buffer): %zu\n", sizeof(buffer)); // 10032 printf("strlen(buffer): %zu\n", strlen(buffer)); // 233 34 return 0;35}$ ./string_size
sizeof(str): 6 bytes
strlen(str): 5 characters
--- Address Calculation for "Hello" ---
Base Address: 0x7ffd5c3e1a40
Index | Char | Address | Calculation
----------------------------------------------
0 | 'H' | 0x7ffd5c3e1a40 | Base + 0
1 | 'e' | 0x7ffd5c3e1a41 | Base + 1
2 | 'l' | 0x7ffd5c3e1a42 | Base + 2
3 | 'l' | 0x7ffd5c3e1a43 | Base + 3
4 | 'o' | 0x7ffd5c3e1a44 | Base + 4
5 | \0 | 0x7ffd5c3e1a45 | Base + 5
----------------------------------------------
sizeof(buffer): 100
strlen(buffer): 2
📌 Notice: Each address differs by only 1 byte (1a40 → 1a41 → 1a42...) because sizeof(char) = 1
📍 Address Calculation in Strings
Since strings are just character arrays, address calculation is simpler than numeric arrays. Each char is exactly 1 byte, so the formula simplifies beautifully!
🔢 String Address Formula
Address of str[i] = Base Address + i
Since sizeof(char) = 1, the formula becomes: Base + (i × 1) = Base + i
Base Address
Address of first character str[0]
i (Index)
Position of character (0, 1, 2...)
Example: char str[] = "Hello" with Base = 5000
5000
[0]
5001
[1]
5002
[2]
5003
[3]
5004
[4]
5005
[5]
| Index (i) | Character | Calculation | Address |
|---|---|---|---|
| 0 | 'H' | 5000 + 0 | 5000 |
| 1 | 'e' | 5000 + 1 | 5001 |
| 2 | 'l' | 5000 + 2 | 5002 |
| 3 | 'l' | 5000 + 3 | 5003 |
| 4 | 'o' | 5000 + 4 | 5004 |
| 5 | '\0' | 5000 + 5 | 5005 |
📝 This program prints each character's memory address and demonstrates pointer arithmetic — showing how ptr+2 moves 2 bytes forward.
1#include <stdio.h>23int main() {4 char str[] = "Hello";5 6 // Base address (address of first character)7 printf("Base Address (str or &str[0]): %p\n\n", (void*)str);8 9 // Demonstrate address calculation10 printf("Character addresses in \"Hello\":\n");11 for (int i = 0; str[i] != '\0'; i++) {12 printf("str[%d] = '%c' at address %p (Base + %d)\n", 13 i, str[i], (void*)&str[i], i);14 }15 printf("str[5] = '\\0' at address %p (Base + 5)\n", (void*)&str[5]);16 17 // Pointer arithmetic with strings18 printf("\nPointer arithmetic:\n");19 char *ptr = str;20 printf("ptr = %p (points to '%c')\n", (void*)ptr, *ptr);21 printf("ptr + 2 = %p (points to '%c')\n", (void*)(ptr + 2), *(ptr + 2));22 printf("ptr + 4 = %p (points to '%c')\n", (void*)(ptr + 4), *(ptr + 4));23 24 return 0;25}💡 Why Strings Are Simpler
For other data types, address = base + (i × size). But since sizeof(char) = 1, strings follow the simplest formula: address = base + i.
This is why pointer arithmetic with strings is so intuitive — incrementing a char*pointer by 1 moves exactly 1 byte to the next character!
🔗 Pointer Arithmetic with Strings
Understanding address calculation helps you understand pointer arithmetic:
Array Notation
str[3]
Access 4th character directly
Pointer Notation
*(str + 3)
Base + 3, then dereference
Both are equivalent! str[i] is just syntactic sugar for *(str + i)
04Reading Strings from User
scanf("%s", str) - Limited
- • Stops at first whitespace
- • No buffer overflow protection
- • Use %99s for size limit (buffer-1)
fgets(str, size, stdin) - Recommended
- • Reads entire line including spaces
- • Built-in buffer overflow protection
- • Includes newline character \n
📝 This interactive program reads user input using both scanf (limited) and fgets (recommended), showing how to handle the input buffer properly.
1#include <stdio.h>2#include <string.h>34int main() {5 char name[50];6 char city[50];7 8 // Method 1: scanf (stops at space)9 printf("Enter first name: ");10 scanf("%49s", name); // %49s prevents overflow11 printf("Name: %s\n", name);12 13 // Clear input buffer after scanf14 while (getchar() != '\n');15 16 // Method 2: fgets (reads full line) - RECOMMENDED17 printf("Enter city name: ");18 fgets(city, sizeof(city), stdin);19 20 // Remove trailing newline from fgets21 city[strcspn(city, "\n")] = '\0';22 23 printf("City: %s\n", city);24 25 return 0;26}💡 Best Practice
Always use fgets() for reading strings. It's safer because it limits how many characters are read and prevents buffer overflow attacks.
05String Functions (<string.h>)
The <string.h> library provides many useful functions for working with strings. You must include this header to use these functions:
| Function | Prototype | Returns |
|---|---|---|
| strlen | size_t strlen(const char *s) | Length of string (not counting \0) |
| strcpy | char *strcpy(char *dest, const char *src) | Pointer to dest |
| strcat | char *strcat(char *dest, const char *src) | Pointer to dest |
| strcmp | int strcmp(const char *s1, const char *s2) | 0 if equal, <0 if s1<s2, >0 if s1>s2 |
| strchr | char *strchr(const char *s, int c) | Pointer to char, or NULL if not found |
| strstr | char *strstr(const char *s1, const char *s2) | Pointer to substring, or NULL if not found |
📝 This program demonstrates the 5 most important string functions: strlen, strcpy, strcat, strcmp, and strchr. Each function is used with a practical example.
1#include <stdio.h>2#include <string.h>34int main() {5 // strlen - Get length6 char msg[] = "Hello";7 printf("Length: %zu\n", strlen(msg)); // 58 9 // strcpy - Copy string10 char dest[20];11 strcpy(dest, "World");12 printf("Copied: %s\n", dest); // World13 14 // strcat - Concatenate15 char greeting[50] = "Hello, ";16 strcat(greeting, "World!");17 printf("Joined: %s\n", greeting); // Hello, World!18 19 // strcmp - Compare (returns 0 if equal)20 char a[] = "apple";21 char b[] = "banana";22 int result = strcmp(a, b);23 if (result == 0) {24 printf("Strings are equal\n");25 } else if (result < 0) {26 printf("%s comes before %s\n", a, b); // This prints27 } else {28 printf("%s comes after %s\n", a, b);29 }30 31 // strchr - Find character32 char *found = strchr("Hello", 'l');33 if (found) {34 printf("Found 'l' at position: %ld\n", found - "Hello"); // 235 }36 37 return 0;38}🔍 How These String Functions Work
strlen("Hello") — Counts characters until \0. Returns 5 (doesn't count the null terminator).
strcpy(dest, "World") — Copies each character from source to destination, including \0.
strcat(greeting, "World!") — Finds the \0 in greeting, then appends source characters there.
strcmp("apple", "banana") — Compares char by char. Returns <0 because 'a' (97) < 'b' (98) in ASCII.
strchr("Hello", 'l') — Returns pointer to first 'l'. Subtract string start to get index: position 2.
⚠️ Buffer Overflow Warning
strcpy() and strcat() don't check buffer sizes! Use strncpy() and strncat() for safer alternatives:
strncpy(dest, src, sizeof(dest) - 1); // Saferdest[sizeof(dest) - 1] = '\0'; // Ensure null termination06Comparing Strings
❌ You Cannot Use == to Compare Strings!
char a[] = "Hello";char b[] = "Hello";if (a == b) { // WRONG! Compares memory addresses, not content printf("Equal"); // This won't print!}📝 This program shows the correct way to compare strings using strcmp(). It demonstrates equal strings, different strings, and alphabetical ordering.
1#include <stdio.h>2#include <string.h>34int main() {5 char str1[] = "Hello";6 char str2[] = "Hello";7 char str3[] = "World";8 9 // Correct way: Use strcmp()10 if (strcmp(str1, str2) == 0) {11 printf("str1 and str2 are EQUAL\n"); // This prints!12 }13 14 if (strcmp(str1, str3) != 0) {15 printf("str1 and str3 are DIFFERENT\n"); // This prints!16 }17 18 // strcmp returns:19 // 0 if strings are equal20 // <0 if str1 comes before str2 alphabetically21 // >0 if str1 comes after str2 alphabetically22 23 printf("strcmp(\"apple\", \"banana\"): %d\n", strcmp("apple", "banana")); // -124 printf("strcmp(\"cat\", \"car\"): %d\n", strcmp("cat", "car")); // positive25 printf("strcmp(\"hello\", \"hello\"): %d\n", strcmp("hello", "hello")); // 026 27 return 0;28}07Common String Mistakes
❌ Forgetting Null Terminator
char str[5] = {'H', 'e', 'l', 'l', 'o'}; // No \0!printf("%s", str); // Undefined behavior - prints garbage after "Hello"❌ Buffer Too Small
char str[5] = "Hello"; // Needs 6 bytes! (5 chars + \0)// This may cause overflow❌ Modifying String Literals
char *str = "Hello";str[0] = 'J'; // CRASH! String literals are read-only❌ Using = to Assign Strings
char str[10];str = "Hello"; // ERROR! Cannot assign arrays like this// Correct way:strcpy(str, "Hello");08Summary
What You Learned:
- ✓Strings: Character arrays ending with \0 (null terminator)
- ✓Memory: String needs length + 1 bytes (for \0)
- ✓Input: Use fgets() for safe string input
- ✓Functions: strlen, strcpy, strcat, strcmp from <string.h>
- ✓Comparison: Use strcmp(), not == operator
09Next Steps
Continue learning about other derived data types: