Skip to content

C Strings

In C, a string is not a built-in fundamental type like int or float. Instead, a string is conventionally represented as an array of characters (char) terminated by a special null character, '\0' (which has an ASCII value of 0).

This is often referred to as a “null-terminated string” or “C-style string”. The null character marks the end of the string data within the array.

There are several ways to declare and initialize strings:

1. Using a String Literal: The most common way. The compiler automatically allocates enough space for the characters plus the null terminator.

char message[] = "Hello"; // Compiler allocates 6 chars ('H','e','l','l','o','\0')
char *str_ptr = "World"; // Creates a string literal (often in read-only memory),
// str_ptr points to its first character.

Warning: Attempting to modify a string literal pointed to by a pointer (like str_ptr[0] = 'J';) results in undefined behavior (often a crash).

2. Specifying Size and Using a String Literal: Ensure the size is large enough for the string content plus the null terminator.

char greeting[10] = "Hi"; // Allocates 10 chars. Initialized to 'H','i','\0'.
// Remaining 7 chars are initialized to '\0'.

3. Using an Initializer List of Characters: If you use this method, you must explicitly include the null terminator.

char word[4] = {'b', 'y', 'e', '\0'}; // Correctly null-terminated
char bad_word[3] = {'o', 'o', 'p'}; // NOT a valid C string! Missing '\0'.

The standard I/O library (<stdio.h>) provides functions for handling strings:

  • printf with %s: Prints a null-terminated string.
  • scanf with %s: Reads a sequence of non-whitespace characters into a character array. WARNING: Extremely unsafe as it doesn’t check buffer boundaries. Easily leads to buffer overflows. Avoid using scanf("%s", ...) without a width limit.
  • fgets: Reads a line of text (including spaces, up to a newline or specified limit) from a stream (like stdin) into a character array. Much safer than scanf as it takes the buffer size as an argument.
  • puts: Prints a string followed by a newline character.

Example using fgets and printf:

#include <stdio.h>
#include <string.h> // For strcspn
#define BUFFER_SIZE 50
int main(void) {
char name[BUFFER_SIZE];
printf("Enter your name: ");
// Safely read input using fgets
if (fgets(name, BUFFER_SIZE, stdin) != NULL) {
// Remove trailing newline character if present (fgets includes it)
name[strcspn(name, "\n")] = 0;
printf("Hello, %s!\n", name);
} else {
printf("Error reading input.\n");
}
return 0;
}

Common String Manipulation Functions (<string.h>)

Section titled “Common String Manipulation Functions (<string.h>)”

The C standard library provides a set of functions in &lt;string.h&gt; for common string operations. Be very careful with functions that don’t take buffer sizes, as they can easily cause buffer overflows if the destination buffer isn’t large enough.

FunctionDescriptionSafety Considerations
strlen(s)Returns the length of string s (excluding the null terminator).Generally safe if s is properly null-terminated.
strcpy(dest, src)Copies string src (including \0) into dest.UNSAFE. Does not check if dest is large enough. Easily causes buffer overflows. Avoid.
strncpy(dest, src, n)Copies at most n characters from src to dest.Safer than strcpy, but has pitfalls: May not null-terminate dest if src length is >= n. Always manually null-terminate: dest[n-1] = '\0'; if size is n.
strcat(dest, src)Appends string src to the end of string dest.UNSAFE. Does not check if dest has enough space for the combined string + \0. Avoid.
strncat(dest, src, n)Appends at most n characters from src to dest. Adds a null terminator.Safer than strcat, but ensure dest buffer size accommodates original length + n + 1.
strcmp(s1, s2)Compares string s1 and s2 lexicographically. Returns 0 if equal, <0 if s1<s2, >0 if s1>s2.Generally safe if both strings are null-terminated.
strncmp(s1, s2, n)Compares at most n characters of s1 and s2.Safer version for comparing potentially non-null-terminated buffers or prefixes.
strchr(s, c)Returns a pointer to the first occurrence of character c in string s, or NULL if not found.Safe if s is null-terminated.
strstr(haystack, needle)Returns a pointer to the first occurrence of string needle within string haystack, or NULL if not found.Safe if both strings are null-terminated.

Best Practice: Whenever possible, use functions that include size parameters (like strncpy, snprintf, fgets) and always be aware of your buffer sizes to prevent overflows. Manually check lengths before using unsafe functions, or allocate sufficient memory dynamically.

Example using safer practices:

#include <stdio.h>
#include <string.h>
#include <stddef.h> // For size_t
int main(void) {
char firstName[] = "Ada";
char lastName[] = "Lovelace";
char fullName[50]; // Ensure buffer is large enough
size_t lenFirstName = strlen(firstName);
size_t lenLastName = strlen(lastName);
size_t bufferSize = sizeof(fullName);
// Use snprintf for safe concatenation (recommended)
int written = snprintf(fullName, bufferSize, "%s %s", firstName, lastName);
if (written > 0 && (size_t)written < bufferSize) {
printf("Full Name (snprintf): %s\n", fullName);
printf("Length: %zu\n", strlen(fullName)); // Or use 'written'
} else {
fprintf(stderr, "Error creating full name or buffer too small.\n");
}
// --- Alternative using strncpy/strncat (more manual) ---
char fullNameManual[50];
// Ensure space for first name, space, last name, null terminator
if (lenFirstName + 1 + lenLastName + 1 <= sizeof(fullNameManual)) {
strncpy(fullNameManual, firstName, sizeof(fullNameManual) - 1);
fullNameManual[sizeof(fullNameManual) - 1] = '\0'; // Ensure null termination
strncat(fullNameManual, " ", sizeof(fullNameManual) - strlen(fullNameManual) - 1);
strncat(fullNameManual, lastName, sizeof(fullNameManual) - strlen(fullNameManual) - 1);
printf("Full Name (manual): %s\n", fullNameManual);
printf("Length: %zu\n", strlen(fullNameManual));
} else {
fprintf(stderr, "Manual buffer too small.\n");
}
return 0;
}

Output:

Full Name (snprintf): Ada Lovelace
Length: 11
Full Name (manual): Ada Lovelace
Length: 11

Proper string handling is critical in C to avoid security vulnerabilities and program crashes.