Strings in C — char Arrays
Unlike most languages, C has no built-in string type. A string in C is simply an array of characters that ends with a special null character '\0'. This null terminator tells C functions where the string ends.
- Declare:
char name[50];— room for 49 characters + 1 null terminator - Initialize:
char city[] = "Delhi";— C adds'\0'automatically - Access:
city[0]gives'D', just like a normal array
Memory layout of char city[] = "Delhi"
#include <stdio.h> int main() { // Method 1: declare with fixed size char name[50]; printf("Enter your name: "); scanf("%s", name); // No & needed — array IS a pointer // Method 2: initialize directly char city[] = "Delhi"; char greeting[30] = "Hello!"; printf("Name: %s\n", name); printf("City: %s\n", city); printf("Greeting: %s\n", greeting); // Access individual characters printf("First char of city: %c\n", city[0]); // D return 0; }
scanf("%s") only reads "Ananta". To read a full line with spaces, use fgets(name, 50, stdin); instead.
%s with printf and scanf for strings, and %c for a single character. No & needed in scanf for a char array — the array name is already a memory address.
String Functions — string.h
C provides a library of ready-made string functions via #include <string.h>. These save you from writing common operations manually every time.
| Function | What it Does | Example | Result |
|---|---|---|---|
| strlen(s) | Length of string (not counting \0) | strlen("Delhi") | 5 |
| strcpy(dst, src) | Copy src into dst | strcpy(a, "Hi") | a = "Hi" |
| strcat(dst, src) | Append src onto end of dst | strcat(a, " World") | a = "Hi World" |
| strcmp(a, b) | Compare two strings (0 = equal) | strcmp("abc","abc") | 0 |
| strupr(s) | Convert to uppercase | strupr("hello") | "HELLO" |
| strlwr(s) | Convert to lowercase | strlwr("HELLO") | "hello" |
#include <stdio.h> #include <string.h> // Required for string functions int main() { char a[50] = "Hello"; char b[50] = " World"; printf("Length of a: %lu\n", strlen(a)); // 5 strcat(a, b); // a = "Hello World" printf("After strcat: %s\n", a); char copy[50]; strcpy(copy, a); // copy = "Hello World" printf("Copied: %s\n", copy); // Compare: 0 means equal if (strcmp(a, copy) == 0) printf("Strings are equal!\n"); return 0; }
Length of a: 5 After strcat: Hello World Copied: Hello World Strings are equal!
a = b does NOT copy a string — it causes a compiler error or wrong result. Always use strcpy(a, b). Similarly, never use == to compare strings — always use strcmp().
Pointers — Memory Addresses
A pointer is a variable that stores the memory address of another variable — not the value itself, but where the value lives in RAM. This is the most powerful and unique concept in C.
- & operator — "address of" — gives the memory address of a variable
- * operator — "dereference" — reads or changes the value at that address
- Pointer declaration:
int *p;— p is a pointer that will point to an int
How a Pointer Works in Memory
#include <stdio.h> int main() { int age = 25; int *p; // Declare a pointer to int p = &age; // p stores the ADDRESS of age printf("Value of age: %d\n", age); // 25 printf("Address of age: %p\n", &age); // 0x... (memory address) printf("Value of p: %p\n", p); // same address as &age printf("Value at *p: %d\n", *p); // 25 (dereference) // Change the original variable THROUGH the pointer *p = 30; printf("age is now: %d\n", age); // 30! return 0; }
Value of age: 25 Address of age: 0x7fff5ab4c Value of p: 0x7fff5ab4c Value at *p: 25 age is now: 30
int *p; — here * means "p is a POINTER to int" (declaration)*p = 30; — here * means "go to the address in p and change the value" (dereference)Same symbol, two completely different meanings depending on context.
int *p; followed immediately by *p = 5; is dangerous — p points to a random address in memory. Always assign p = &someVariable; before dereferencing, or set int *p = NULL; to mark it as unused.
Pointers & Functions — Call by Reference
By default C passes values to functions as copies — changes inside the function don't affect the original. But if you pass a pointer, the function can modify the original variable directly. This is called call by reference.
#include <stdio.h> // Takes pointers — can change original variables void swap(int *a, int *b) { int temp = *a; // save value at address a *a = *b; // put value from b into address a *b = temp; // put saved value into address b } int main() { int x = 10, y = 20; printf("Before: x=%d, y=%d\n", x, y); // 10, 20 swap(&x, &y); // pass addresses printf("After: x=%d, y=%d\n", x, y); // 20, 10 return 0; }
scanf("%d", &age) — you pass the address of age so scanf can write the value directly into it. Now you understand the & from Day 1!
Pointers & Arrays — The Connection
In C, an array name is already a pointer — it holds the address of the first element. This means you can use pointer arithmetic to walk through an array, and it explains why scanf doesn't need & for char arrays.
arris the same as&arr[0]— address of first elementarr + 1points to the second element,arr + 2to third, etc.*(arr + i)is exactly the same asarr[i]
#include <stdio.h> int main() { int scores[5] = {10, 20, 30, 40, 50}; int *p = scores; // p points to first element printf("Using array notation: "); for (int i = 0; i < 5; i++) printf("%d ", scores[i]); // normal way printf("\nUsing pointer notation: "); for (int i = 0; i < 5; i++) printf("%d ", *(p + i)); // pointer arithmetic printf("\nBoth give same result!\n"); return 0; }
Using array notation: 10 20 30 40 50 Using pointer notation: 10 20 30 40 50 Both give same result!
&x → "give me the address of x"*p → "give me the value at the address stored in p"They are opposites —
& goes from value→address, * goes from address→value.
Quick Quiz — Test Yourself
What character marks the end of every string in C?
You have char a[20] = "Hello"; and char b[20] = "World"; — how do you copy b into a correctly?
Given int x = 5; int *p = &x; — what does *p give you?
Why does scanf("%d", &age) need the & before age?
Given int arr[] = {5,10,15}; — what is *(arr + 2)?
Lesson Checklist
- I know a C string is a char array ending with '\0'
- I can declare and initialize strings both ways
- I understand why scanf needs no & for char arrays
- I can use strlen, strcpy, strcat, strcmp
- I know never to use = or == with strings
- I understand what a pointer is — a variable holding an address
- I can use & (address-of) and * (dereference) correctly
- I understand call by reference using pointers
- I know that an array name is already a pointer
- I can use pointer arithmetic: *(arr + i) == arr[i]
- I completed the quiz
Day 4 Preview
- 🏗️ Structures (struct) — group different data types together Day 4
- 🔗 Nested Structures — structs inside structs Day 4
- 🗃️ Structure Arrays — store multiple records Day 4
- 📦 Union & Enum — shared memory and named constants Day 4