C Strings
Introduction to Strings in C
In C programming, a string is a sequence of characters terminated with a null character '\0'. Strings are actually one-dimensional arrays of characters, but they have special properties that make them different from regular character arrays.
C doesn't have a built-in string data type like some other languages. Instead, strings are implemented as arrays of characters with a null terminator to indicate the end of the string.
String Declaration and Initialization
Strings can be declared and initialized in several ways:
1. As a character array: char str[10];
2. With initialization: char str[10] = "Hello";
3. Without size specification: char str[] = "Hello";
4. As a pointer: char *str = "Hello";
#include <stdio.h>
int main(void) {
char str1[10];
char str2[10] = "Hello";
char str3[] = "Hello";
const char *str4 = "Hello"; // pointer to string literal (read-only)
str1[0] = 'H';
str1[1] = 'i';
str1[2] = '\0';
printf("str1: %s\n", str1);
printf("str2: %s\n", str2);
printf("str3: %s\n", str3);
printf("str4: %s\n", str4);
return 0;
}
str1: Hi str2: Hello str3: Hello str4: Hello
Null Terminator
The null character '\0' is crucial for C strings. It marks the end of the string and is automatically added by the compiler when you initialize a string with double quotes.
Without the null terminator, C string functions won't know where the string ends and may read past the intended data, leading to undefined behavior.
#include <stdio.h>
#include <string.h>
int main(void) {
char properString[6] = "Hello";
printf("Proper string: %s (length: %zu)\n", properString, strlen(properString));
char notAString[5] = {'H', 'e', 'l', 'l', 'o'};
printf("Not a string: %s (undefined behavior)\n", notAString);
return 0;
}
Proper string: Hello (length: 5) Not a string: Hello� (undefined behavior)
String Input and Output
C provides several ways to read and write strings:
• printf() and puts() for output
• fgets() for input (reads up to n-1 chars and adds a terminator)
• scanf() with a field width (e.g., "%49s") to avoid overflow
Avoid gets() — it is unsafe and removed from the C standard.
#include <stdio.h>
#include <string.h>
int main(void) {
char name[50];
printf("Enter your name: ");
if (fgets(name, sizeof name, stdin)) {
name[strcspn(name, "\n")] = '\0'; // strip trailing newline if present
printf("Hello, %s!\n", name);
puts(name);
}
return 0;
}
Enter your name: John Hello, John! John
String Storage in Memory
Strings can be stored in different memory segments:
1. Stack: For arrays declared with fixed size
2. Heap: For dynamically allocated strings
3. Read-only memory: For string literals
Understanding where strings are stored is important for memory management and avoiding errors.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char stackString[20] = "Stack string"; // stack
char *heapString = malloc(20); // heap
if (!heapString) return 1;
strcpy(heapString, "Heap string");
const char *literalString = "Literal string"; // read-only storage
printf("Stack: %s\n", stackString);
printf("Heap: %s\n", heapString);
printf("Literal: %s\n", literalString);
stackString[0] = 's';
heapString[0] = 'h';
printf("Modified stack: %s\n", stackString);
printf("Modified heap: %s\n", heapString);
free(heapString);
return 0;
}
Stack: Stack string Heap: Heap string Literal: Literal string Modified stack: stack string Modified heap: heap string
Common String Operations
Basic string operations can be performed using standard library functions or by manually iterating through characters:
• Finding length
• Copying strings
• Comparing strings
• Concatenating strings
• Searching within strings
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[20] = "Hello";
char str2[20] = "World";
char str3[20];
printf("Length of '%s': %zu\n", str1, strlen(str1));
strcpy(str3, str1);
printf("After copy: %s\n", str3);
// Ensure space remains before concatenation in real code
strcat(str3, " ");
strcat(str3, str2);
printf("After concatenation: %s\n", str3);
int result = strcmp(str1, str2);
if (result == 0) {
printf("'%s' equals '%s'\n", str1, str2);
} else if (result < 0) {
printf("'%s' comes before '%s'\n", str1, str2);
} else {
printf("'%s' comes after '%s'\n", str1, str2);
}
return 0;
}
Length of 'Hello': 5 After copy: Hello After concatenation: Hello World 'Hello' comes before 'World'
Best Practices
1. Always ensure strings are null-terminated.
2. Use fgets() for input (or scanf with a width limit like "%49s"); avoid gets().
3. Check buffer sizes to prevent overflow; for output to buffers prefer snprintf().
4. Be careful with string literals — they are read-only (use const char*).
5. If you must use strncpy(), remember it may not null-terminate on truncation; add the terminator yourself. Often, snprintf() or explicit length-checked copies are clearer.
6. Remember to free dynamically allocated strings.