String Basics
A C string is like a necklace ending with a transparent bead -- each bead is a character, and the last one is the invisible terminator \0 that signals "the necklace ends here".
Character Arrays and Strings
C has no dedicated string type. A string is essentially a character array terminated by \0 (the null character). The ASCII value of \0 is 0, and it marks the end of the string.
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
This array has 6 elements: 5 visible characters plus 1 \0. Without \0, it is just an ordinary character array and cannot be used as a string.
String literals (double quotes) automatically append \0 at the end:
char str[] = "Hello";
The array length is 6 (5 characters + 1 \0); the compiler calculates it automatically. You can also specify a larger length; the extra positions are filled with \0:
char str[10] = "Hello";
str[5] through str[9] are all \0.
'H' denote a character (1 byte); double quotes "Hello" denote a string (with an implicit \0). They are not the same.
String Declaration and Initialization
Character Array Style
char s1[] = "abc";
char s2[10] = "abc";
char s3[] = {'a', 'b', 'c', '\0'};
All three are equivalent to the string "abc". Note that s3 requires a manually added \0.
Character Pointer Style
const char *s4 = "abc";
s4 points to the first character of a string literal. String literals are stored in a read-only region; attempting to modify them is undefined behavior:
s4[0] = 'A';
This is wrong. Character arrays, however, are modifiable:
s1[0] = 'A';
Legal -- the contents of s1 become "Abc".
const when pointing a pointer at a string literal; the compiler will warn you if you try to modify it.
Pointers vs Arrays
char arr[] = "hello";
const char *ptr = "hello";
arris an array: memory is allocated on the stack, contents can be modified,sizeof(arr)is 6ptris a pointer: it points to a string literal in read-only memory,sizeof(ptr)is the pointer size (4 or 8 bytes)
String Input and Output
printf and scanf
Use the %s format specifier for string input and output:
char name[20];
scanf("%s", name);
printf("Hello, %s!\n", name);
scanf stops reading at whitespace (space, newline, tab), so it cannot read an entire line containing spaces.
scanf does not check the buffer size; input exceeding the array length causes an overflow. You can limit the read length:
scanf("%19s", name);
This reads at most 19 characters, leaving 1 position for \0.
puts and gets
puts outputs a string and automatically appends a newline:
char msg[] = "Hello";
puts(msg);
This is equivalent to printf("%s\n", msg);.
gets reads an entire line (including spaces) until a newline:
char line[100];
gets(line);
fgets
fgets is the safe replacement for gets:
char line[100];
fgets(line, sizeof(line), stdin);
The parameters are: the storage buffer, the maximum number of bytes to read (including \0), and the input stream. fgets retains the newline at the end of the string (if a newline was read and there is still space).
Common pattern for removing the trailing newline:
#include <stdio.h>
#include <string.h>
int main(void) {
char line[100];
fgets(line, sizeof(line), stdin);
int len = strlen(line);
if (len > 0 && line[len - 1] == '\n') {
line[len - 1] = '\0';
}
printf("[%s]\n", line);
return 0;
}
Example
Read the user's name and a line of self-introduction:
#include <stdio.h>
#include <string.h>
void trim_newline(char *s) {
int len = strlen(s);
if (len > 0 && s[len - 1] == '\n') {
s[len - 1] = '\0';
}
}
int main(void) {
char name[30];
char intro[200];
printf("Enter your name: ");
fgets(name, sizeof(name), stdin);
trim_newline(name);
printf("Introduce yourself: ");
fgets(intro, sizeof(intro), stdin);
trim_newline(intro);
printf("\n--- Personal Info ---\n");
printf("Name: %s\n", name);
printf("Intro: %s\n", intro);
return 0;
}
Enter your name: Alice
Introduce yourself: I am a C beginner
--- Personal Info ---
Name: Alice
Intro: I am a C beginner
The strlen Function
strlen is declared in <string.h> and returns the length of the string (not including \0):
#include <string.h>
char s[] = "Hello";
printf("%zu\n", strlen(s));
Output: 5. Note that sizeof(s) is 6 (including \0), while strlen(s) is 5 (excluding \0).
How strlen works: it counts characters from the beginning until it encounters \0:
size_t my_strlen(const char *s) {
size_t len = 0;
while (s[len] != '\0') {
len++;
}
return len;
}
If a character array does not end with \0, strlen will keep reading until it happens to encounter a zero byte, which is very dangerous.
Introduction to Character Pointers
A character pointer can point to either a character array or a string literal:
char arr[] = "world";
const char *ptr = "world";
ptr = arr;
printf("%s\n", ptr);
A pointer can be reassigned to point to a different string, but an array name is a constant and cannot be modified:
ptr = "another string";
Legal. But:
arr = "another string";
Illegal -- an array name cannot be assigned.
Traversing a string with a pointer:
const char *p = "Hello";
while (*p != '\0') {
printf("%c", *p);
p++;
}
printf("\n");
*p dereferences to get the current character; p++ moves to the next character position. The pointer stride is determined by the pointed-to type; char * moves 1 byte per step.
Example
Print a string in reverse using a character pointer:
#include <stdio.h>
#include <string.h>
void print_reverse(const char *s) {
const char *p = s + strlen(s) - 1;
while (p >= s) {
putchar(*p);
p--;
}
putchar('\n');
}
int main(void) {
print_reverse("Hello");
print_reverse("ABCDEF");
return 0;
}
olleH
FEDCBA
First, move the pointer p to the last character of the string (one position before \0), then output characters from back to front.
❓ FAQ
'a' and "a"?'a' is a character constant occupying 1 byte; "a" is a string constant occupying 2 bytes ('a' plus '\0'), and its type is char[].sizeof and strlen give different results for strings?sizeof returns the total memory occupied by the array (including \0); strlen returns the number of characters before \0.fgets reads a newline?fgets stores the newline in the buffer. You typically need to manually check for it and replace it with \0 to remove it.📖 Summary
- C strings are character arrays terminated by
\0;\0is what string functions use to detect the end - Character arrays allow content modification; character pointers pointing to literals do not
- Use
fgetsinstead ofgetsfor reading strings; always specify the buffer size strlenreturns the number of effective characters;sizeofreturns the total array size- Character pointers can traverse a string, moving one char position per step
📝 Exercises
- Write a program that uses
fgetsto read a line of text and counts the number of letters, digits, and other characters. - Write a function
void str_replace_char(char *s, char old, char new_ch)that replaces all occurrences ofoldin stringswithnew_ch. - Write a function that calculates the length of a string using character pointers, without using
strlen.



