(A string array = array where each element is a string)
In C, a string is an array of characters ending with \\0.
So an array of strings is actually a 2D character array.
Think of it like a list of words, where each word is a character array.
✅ Declaration Syntax
char names[3][10];🔍 What this means:
3= Number of strings (rows)10= Maximum length of each string (columns), including\\0
📌 Example 1: Declaration + Initialization
char fruits[3][10] = {"Apple", "Mango", "Banana"};Index | Value (String) |
|---|---|
0 | "Apple" |
1 | "Mango" |
2 | "Banana" |
Each row is a complete string. Max 9 visible characters + \\0.
🔄 Accessing and Printing Strings
printf("%s", fruits[0]); // Apple
printf("%s", fruits[1]); // Mango🔁 Using Loops to Access All Strings
for(int i = 0; i < 3; i++) {
printf("Fruit %d: %s\\n", i+1, fruits[i]);
}🧾 Taking Input for Array of Strings
Let’s take 3 student names from the user:
char students[3][20];
for(int i = 0; i < 3; i++) {
printf("Enter name %d: ", i+1);
scanf("%s", students[i]); // Takes one word only
}Enter name 1: Alice
Enter name 2: Bob
Enter name 3: Charlie✅ Explanation:
char students[3][20];This creates a 2D character array — meaning 3 strings, each of maximum 19 characters + 1 for null terminator
\\0.The
forloop runs 3 times — asking the user to enter a name each time.scanf("%s", students[i]);This reads a single word (string) from input and stores it in the respective row of
students.
⚠️ Note: scanf("%s") will stop at a space. For full names, use fgets().
🧰 Behind the Scenes – How It Works in Memory
char lang[3][10] = {"C", "Python", "Java"};This is a 2D char array like:
📦 Memory Representation of lang[3][10]
<div class="infographic-c2dstr">
<style>
.infographic-c2dstr {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--code-bg: #1e1e2e;
--code-text: #d4d4e0;
--syn-keyword: #c586c0;
--syn-func: #dcdcaa;
--syn-string: #ce9178;
--syn-comment: #6a9955;
--warn: #b45309;
--warn-soft: #fdf0dc;
--null-color: #9a6b2f;
}
.infographic-c2dstr[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--code-bg: #0d0d14;
--code-text: #d4d4e0;
--warn: #e0a458;
--warn-soft: #3a2c14;
--null-color: #d4a35f;
}
.infographic-c2dstr {
box-sizing: border-box;
max-width: 760px;
margin: 0 auto;
background: var(--paper);
color: var(--ink);
font-family: 'Inter', -apple-system, sans-serif;
padding: 0 clamp(1rem, 4vw, 2.25rem) 1.25rem;
}
.infographic-c2dstr *, .infographic-c2dstr *::before, .infographic-c2dstr *::after {
box-sizing: border-box;
}
.infographic-c2dstr h1 {
font-family: 'Fraunces', Georgia, serif;
font-weight: 600;
font-size: clamp(1.4rem, 3.5vw, 1.9rem);
margin: 1.25rem 0 0.25rem;
}
.infographic-c2dstr .subhead { color: var(--ink-soft); font-size: 0.85rem; margin-bottom: 1rem; }
.infographic-c2dstr .code-panel {
background: var(--code-bg);
color: var(--code-text);
border-radius: 8px;
padding: 0.65rem 0.9rem;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem;
line-height: 1.6;
margin-bottom: 0.8rem;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
max-width: 100%;
}
.infographic-c2dstr .syn-keyword { color: var(--syn-keyword); }
.infographic-c2dstr .syn-func { color: var(--syn-func); }
.infographic-c2dstr .syn-string { color: var(--syn-string); }
.infographic-c2dstr .syn-comment { color: var(--syn-comment); }
.infographic-c2dstr .field-row { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; margin-bottom: 0.9rem; }
.infographic-c2dstr .field-row label { font-size: 0.82rem; color: var(--ink-soft); }
.infographic-c2dstr .field-row input[type="text"] {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.86rem;
padding: 0.32rem 0.5rem;
border-radius: 6px;
border: 1px solid var(--line);
background: var(--paper);
color: var(--ink);
width: 16rem;
max-width: 100%;
}
.infographic-c2dstr .field-row input[type="number"] {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.86rem;
padding: 0.32rem 0.5rem;
border-radius: 6px;
border: 1px solid var(--line);
background: var(--paper);
color: var(--ink);
width: 3.6rem;
}
.infographic-c2dstr .field-row input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.infographic-c2dstr .row2d { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.35rem; }
.infographic-c2dstr .row2d .row-label {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.72rem;
color: var(--ink-soft);
width: 4.2rem;
flex-shrink: 0;
}
.infographic-c2dstr .cellbox {
width: 1.8rem;
height: 1.8rem;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid var(--line);
border-radius: 4px;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.78rem;
background: var(--paper-alt);
flex-shrink: 0;
}
.infographic-c2dstr .cellbox.is-null { color: var(--null-color); font-weight: 700; border-color: var(--null-color); background: transparent; }
.infographic-c2dstr .cellbox.is-pad { border-style: dashed; color: var(--ink-soft); opacity: 0.5; }
.infographic-c2dstr .row-cells { display: flex; gap: 0.25rem; flex-wrap: wrap; }
.infographic-c2dstr .overflow-tag {
font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
color: var(--warn); background: var(--warn-soft); padding: 0.12rem 0.4rem; border-radius: 10px; margin-left: 0.4rem;
}
.infographic-c2dstr .facts { font-size: 0.78rem; color: var(--ink-soft); margin-top: 0.6rem; }
.infographic-c2dstr .takeaway { font-size: 0.82rem; color: var(--ink-soft); margin-top: 1.25rem; border-top: 1px solid var(--line); padding-top: 0.9rem; }
.infographic-c2dstr .takeaway strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-c2dstr * { transition: none !important; }
}
</style>
<h1>🔤 2D Char Array — char arr[rows][cols]</h1>
<p class="subhead">Every row is a fixed-width slot: real characters, then <code style="font-family:'IBM Plex Mono',monospace;">\0</code>, then whatever padding is left.</p>
<div class="code-panel" id="d2s-code"></div>
<div class="field-row">
<label>words (comma separated)</label>
<input type="text" id="d2s-words" value="Apple, Mango, Banana">
<label>max length (cols)</label>
<input type="number" id="d2s-cols" value="10" min="2" max="16">
</div>
<div id="d2s-grid"></div>
<p class="facts" id="d2s-facts"></p>
<p class="takeaway"><strong>Try it:</strong> shrink <code style="font-family:'IBM Plex Mono',monospace;">cols</code> below a word's length and that row truncates — the classic "forgot room for \0" bug. Grow it and you'll see the wasted dashed padding cells.</p>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-c2dstr')
|| document.querySelector('.infographic-c2dstr');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
function $(sel) { return wrapper.querySelector(sel); }
function esc(s) { return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); }
function parseWords(raw) {
return raw.split(',').map(s => s.trim()).filter(s => s.length > 0);
}
const d2sWords = $('#d2s-words');
const d2sCols = $('#d2s-cols');
const d2sCode = $('#d2s-code');
const d2sGrid = $('#d2s-grid');
const d2sFacts = $('#d2s-facts');
function renderD2S() {
const words = parseWords(d2sWords.value);
if (words.length === 0) { d2sGrid.innerHTML = ''; d2sFacts.textContent = ''; return; }
const cols = Math.max(2, Math.min(16, parseInt(d2sCols.value, 10) || 2));
d2sCols.value = cols;
const rows = words.length;
d2sCode.innerHTML = '<span class="syn-keyword">char</span> <span class="syn-func">arr</span>[' + rows + '][' + cols + '] = {' +
words.map(w => '<span class="syn-string">"' + esc(w) + '"</span>').join(', ') + '};';
d2sGrid.innerHTML = '';
let anyOverflow = false;
words.forEach((word, i) => {
let chars = word.split('');
let truncated = false;
if (chars.length + 1 > cols) { chars = chars.slice(0, cols - 1); truncated = true; anyOverflow = true; }
const rowEl = document.createElement('div');
rowEl.className = 'row2d';
const label = document.createElement('div');
label.className = 'row-label';
label.innerHTML = 'arr[' + i + ']' + (truncated ? '<span class="overflow-tag">cut off</span>' : '');
rowEl.appendChild(label);
const cellsEl = document.createElement('div');
cellsEl.className = 'row-cells';
chars.forEach(ch => {
const box = document.createElement('div');
box.className = 'cellbox';
box.textContent = ch;
cellsEl.appendChild(box);
});
const nullBox = document.createElement('div');
nullBox.className = 'cellbox is-null';
nullBox.textContent = '\\0';
cellsEl.appendChild(nullBox);
for (let p = chars.length + 1; p < cols; p++) {
const pad = document.createElement('div');
pad.className = 'cellbox is-pad';
pad.textContent = '\u00b7';
cellsEl.appendChild(pad);
}
rowEl.appendChild(cellsEl);
d2sGrid.appendChild(rowEl);
});
d2sFacts.textContent = rows + ' rows × ' + cols + ' cols = ' + (rows * cols) + ' bytes total (sizeof(arr)).' +
(anyOverflow ? ' Some words no longer fit — they\u2019re silently cut short.' : '');
}
d2sWords.addEventListener('input', renderD2S);
d2sCols.addEventListener('input', renderD2S);
renderD2S();
})();
</script>🔁 So you get 3 rows (strings) and each has 10 columns (characters)
📍 Alternative: Array of Pointers to Strings
This is a more flexible and memory-efficient approach.
char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri"};🔍 In this version:
days[0]is a pointer to a string literal"Mon"These strings are stored in read-only memory
✅ Loop Through It:
char *days[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
for(int i = 0; i < 5; i++) {
printf("%s\\n", days[i]);
}Monday
Tuesday
Wednesday
Thursday
Friday<div class="infographic-cptrstr">
<style>
.infographic-cptrstr {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--code-bg: #1e1e2e;
--code-text: #d4d4e0;
--syn-keyword: #c586c0;
--syn-func: #dcdcaa;
--syn-string: #ce9178;
}
.infographic-cptrstr[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--code-bg: #0d0d14;
--code-text: #d4d4e0;
}
.infographic-cptrstr {
box-sizing: border-box;
max-width: 760px;
margin: 0 auto;
background: var(--paper);
color: var(--ink);
font-family: 'Inter', -apple-system, sans-serif;
padding: 0 clamp(1rem, 4vw, 2.25rem) 1.25rem;
}
.infographic-cptrstr *, .infographic-cptrstr *::before, .infographic-cptrstr *::after {
box-sizing: border-box;
}
.infographic-cptrstr h1 {
font-family: 'Fraunces', Georgia, serif;
font-weight: 600;
font-size: clamp(1.4rem, 3.5vw, 1.9rem);
margin: 1.25rem 0 0.25rem;
}
.infographic-cptrstr .subhead { color: var(--ink-soft); font-size: 0.85rem; margin-bottom: 1rem; }
.infographic-cptrstr .code-panel {
background: var(--code-bg);
color: var(--code-text);
border-radius: 8px;
padding: 0.65rem 0.9rem;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem;
line-height: 1.6;
margin-bottom: 0.8rem;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
max-width: 100%;
}
.infographic-cptrstr .syn-keyword { color: var(--syn-keyword); }
.infographic-cptrstr .syn-func { color: var(--syn-func); }
.infographic-cptrstr .syn-string { color: var(--syn-string); }
.infographic-cptrstr .field-row { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; margin-bottom: 0.9rem; }
.infographic-cptrstr .field-row label { font-size: 0.82rem; color: var(--ink-soft); }
.infographic-cptrstr .field-row input[type="text"] {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.86rem;
padding: 0.32rem 0.5rem;
border-radius: 6px;
border: 1px solid var(--line);
background: var(--paper);
color: var(--ink);
width: 22rem;
max-width: 100%;
}
.infographic-cptrstr .field-row input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.infographic-cptrstr .ptr-row { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.45rem; }
.infographic-cptrstr .ptr-label {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.78rem;
color: var(--ink-soft);
width: 4.5rem;
flex-shrink: 0;
}
.infographic-cptrstr .ptr-arrow { color: var(--ink-soft); font-size: 0.9rem; }
.infographic-cptrstr .ptr-box {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.85rem;
padding: 0.32rem 0.7rem;
border: 1px solid var(--accent);
background: var(--accent-soft);
color: var(--accent);
border-radius: 6px;
}
.infographic-cptrstr .facts { font-size: 0.78rem; color: var(--ink-soft); margin-top: 0.6rem; }
.infographic-cptrstr .takeaway { font-size: 0.82rem; color: var(--ink-soft); margin-top: 1.25rem; border-top: 1px solid var(--line); padding-top: 0.9rem; }
.infographic-cptrstr .takeaway strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-cptrstr * { transition: none !important; }
}
</style>
<h1>🔤 Array of Pointers — char *arr[]</h1>
<p class="subhead">No fixed width, no padding — each element just points to a string literal wherever it lives.</p>
<div class="code-panel" id="ptr-code"></div>
<div class="field-row">
<label>words (comma separated)</label>
<input type="text" id="ptr-words" value="Monday, Tuesday, Wednesday, Thursday, Friday">
</div>
<div id="ptr-list"></div>
<p class="facts" id="ptr-facts"></p>
<p class="takeaway"><strong>Try it:</strong> mix short and long words — every box sizes to fit its own string exactly, since these are just pointers to separately stored literals, not fixed-width rows.</p>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-cptrstr')
|| document.querySelector('.infographic-cptrstr');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
function $(sel) { return wrapper.querySelector(sel); }
function esc(s) { return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); }
function parseWords(raw) {
return raw.split(',').map(s => s.trim()).filter(s => s.length > 0);
}
const ptrWords = $('#ptr-words');
const ptrCode = $('#ptr-code');
const ptrList = $('#ptr-list');
const ptrFacts = $('#ptr-facts');
function renderPtr() {
const words = parseWords(ptrWords.value);
if (words.length === 0) { ptrList.innerHTML = ''; ptrFacts.textContent = ''; return; }
ptrCode.innerHTML = '<span class="syn-keyword">char</span> *<span class="syn-func">arr</span>[] = {' +
words.map(w => '<span class="syn-string">"' + esc(w) + '"</span>').join(', ') + '};';
ptrList.innerHTML = '';
words.forEach((w, i) => {
const row = document.createElement('div');
row.className = 'ptr-row';
row.innerHTML = '<span class="ptr-label">arr[' + i + ']</span><span class="ptr-arrow">→</span><span class="ptr-box">"' + esc(w) + '"</span>';
ptrList.appendChild(row);
});
const longest = Math.max(...words.map(w => w.length));
ptrFacts.textContent = words.length + ' pointers × 8 bytes = ' + (words.length * 8) + ' bytes for the array itself — ' +
'each string literal is stored separately, at whatever length it needs (longest here: ' + longest + ' chars).';
}
ptrWords.addEventListener('input', renderPtr);
renderPtr();
})();
</script>⚔️ Difference: 2D Array vs Array of Pointers
Feature | 2D char array ( | Array of pointers ( |
|---|---|---|
Memory | Fixed size | Dynamically points to literals |
Flexibility | Less (fixed length) | More (different lengths possible) |
Writable | Yes | No (string literals are read-only) |
Used for | User input | Constant lists, menus, etc. |
❌ Common Mistakes
Mistake | Why It's Wrong |
|---|---|
Not reserving space for | Causes unexpected output |
Using | Compares addresses, not content |
Trying to modify string literal in | Causes crash or undefined behavior |
✅ Example: Menu System Using Array of Strings
#include <stdio.h>
int main() {
char *menu[] = {"Start", "Settings", "Help", "Exit"};
for(int i = 0; i < 4; i++) {
printf("%d. %s\\n", i + 1, menu[i]);
}
return 0;
}1. Start
2. Settings
3. Help
4. Exit