Arrays and Strings
Arrays and Strings
An array is a block of memory holding several values of the same type, laid out one after another with no gaps. That physical layout is the whole idea. Because the elements are adjacent and equally sized, the computer can find element number 7 by simple arithmetic: start address plus 7 times the element size. There is no searching involved, which is why array access is fast regardless of the index.
Declaring and using an array
#include <stdio.h>
int main(void)
{
int marks[5] = {88, 74, 91, 63, 79};
printf("First element : %d\n", marks[0]);
printf("Last element : %d\n", marks[4]);
int total = 0;
for (int i = 0; i < 5; i++) {
printf("marks[%d] = %d\n", i, marks[i]);
total += marks[i];
}
printf("Total : %d\n", total);
printf("Average : %.2f\n", (float) total / 5);
return 0;
}
The size in int marks[5] is fixed at compile time and cannot change later. C arrays do not grow.
Indexing starts at zero. An array of size 5 has valid indices 0, 1, 2, 3 and 4. There is no marks[5]. This is not an arbitrary choice: the index is really an offset from the start, and the first element sits at offset zero.
Because of that, for (int i = 0; i < n; i++) is the standard loop shape. Using i <= n walks one element past the end.
What happens outside the bounds
#include <stdio.h>
int main(void)
{
int marks[5] = {88, 74, 91, 63, 79};
int size = sizeof(marks) / sizeof(marks[0]);
printf("Array size in bytes : %zu\n", sizeof(marks));
printf("One element in bytes : %zu\n", sizeof(marks[0]));
printf("Number of elements : %d\n", size);
for (int i = 0; i < size; i++) {
printf("%d ", marks[i]);
}
printf("\n");
return 0;
}
sizeof(array) / sizeof(array[0]) is the standard way to compute the element count, and it beats writing 5 in three different places where one will eventually be changed and the others forgotten. Be aware that this only works where the array itself is visible; once passed to a function it decays to a pointer and the trick silently gives the wrong answer.
Writing marks[7] = 100; on a five-element array compiles cleanly and runs. It writes to whatever memory happens to sit after your array: another variable, a saved return address, anything. The program may print a wrong answer, may crash much later, or may appear to work perfectly on your laptop and fail during evaluation. This is called undefined behaviour, and it is the single most common source of serious bugs in C. Checking your indices is your job, not the compiler's.
Strings are char arrays
C has no string type. A string in C is simply an array of char that ends with a null terminator, the character with value zero, written '\0'.
That terminator is not decoration. Functions such as printf with %s, or strlen, receive only the starting address. They have no idea how long the array is. They walk forward one character at a time and stop when they meet a zero byte. Remove the terminator and they keep walking into unrelated memory.
#include <stdio.h>
int main(void)
{
char a[] = "Delhi";
char b[6] = {'D', 'e', 'l', 'h', 'i', '\0'};
printf("a = %s\n", a);
printf("b = %s\n", b);
printf("Bytes in a : %zu\n", sizeof(a));
for (int i = 0; a[i] != '\0'; i++) {
printf("a[%d] = %c (code %d)\n", i, a[i], a[i]);
}
return 0;
}
sizeof(a) prints 6, not 5. The five letters plus the terminator occupy six bytes. This is why a char[10] holds at most nine usable characters.
The two declarations above are equivalent. char a[] = "Delhi"; lets the compiler count for you and add the '\0' automatically, which is why it is the form you should normally write.
Basic string functions
The standard library provides string handling in string.h. Four functions cover most first-year work.
| Function | What it does |
|---|---|
strlen(s) |
Number of characters before the terminator |
strcpy(dest, src) |
Copies src into dest, terminator included |
strcat(dest, src) |
Appends src to the end of dest |
strcmp(a, b) |
Returns 0 if equal, negative if a sorts first, positive otherwise |
#include <stdio.h>
#include <string.h>
int main(void)
{
char city[30] = "Chennai";
char state[] = "Tamil Nadu";
char full[60];
printf("Length of city : %zu\n", strlen(city));
strcpy(full, city);
strcat(full, ", ");
strcat(full, state);
printf("Joined : %s\n", full);
printf("strcmp equal : %d\n", strcmp("abc", "abc"));
printf("strcmp a vs b : %d\n", strcmp("apple", "banana"));
char word[] = "engineer";
int vowels = 0;
for (int i = 0; word[i] != '\0'; i++) {
char c = word[i];
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
vowels++;
}
}
printf("Vowels in %s : %d\n", word, vowels);
return 0;
}
Note the difference between strlen and sizeof. strlen("Chennai") is 7, the number of characters. sizeof(city) is 30, the size of the box you declared. They answer different questions and confusing them causes real bugs.
Also note that strcmp returns 0 for equal, which reads backwards the first few times. if (strcmp(a, b) == 0) means the strings match.
Comparing strings the wrong way
You cannot compare strings with ==. An array name in an expression becomes the address of its first element, so if (name1 == name2) compares two addresses, not two sets of characters. Two different arrays always sit at different addresses, so the test is false even when the text is identical.
For the same reason you cannot copy with =. full = city; is a compile error. Use strcpy.
Two-dimensional arrays
#include <stdio.h>
int main(void)
{
int table[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%4d", table[i][j]);
}
printf("\n");
}
return 0;
}
Read table[3][4] as three rows of four columns. In memory it is still one flat block, stored row by row. Nested loops walk it, with the outer index for rows and the inner for columns.
Common mistakes
- Off-by-one at the end.
for (i = 0; i <= n; i++)touches one element past the array. Usei < n. - Forgetting the null terminator. Building a string character by character and not writing
'\0'at the end leavesprintf("%s", ...)reading random memory. - Undersized buffer.
char name[5] = "Rohit";has no room for the terminator. Declarechar name[6]or let the compiler size it withchar name[] = "Rohit"; - Comparing with
==. Compares addresses, never contents. Usestrcmp. - Assigning with
=.dest = src;for arrays does not compile. Usestrcpy. strcatpast the end of the destination. The destination must already be large enough for both strings plus the terminator.strcatdoes not check.- Assuming uninitialised arrays are zero. A local
int a[10];contains garbage. Writeint a[10] = {0};to zero it.
Arrays are the first place where C's willingness to let you make mistakes becomes visible, and getting careful about indices now saves a great deal of pain in your data structures course. Practise sums, searches, reversals and vowel counts on the Practice page.