A C array is a fixed-size, contiguous block of same-typed elements with zero automatic bounds checking — reading or writing past the end is legal C syntax that produces undefined behavior, not a caught error. A string is simply a char array by convention, terminated by a null byte (\0) marking where it ends; string.h functions like strlen and strcpy work by scanning forward until they find that byte, which is also why a missing null terminator causes them to keep reading (or writing) past the buffer's actual end.
Strings are char arrays with a hidden extra byte
The 6-character array below actually needs 6 bytes: 5 letters plus the null terminator the compiler adds automatically for a string literal — forgetting to budget space for that byte in a manually-sized buffer is a classic, real bug.
char name[6] = "hello"; // 'h','e','l','l','o','\0' — exactly fills 6 bytes
printf("%s\n", name); // printf scans until it hits the \0
char broken[5] = "hello"; // COMPILE WARNING (or worse): no room for the \0 at allArrays decay to pointers when passed to a function
Inside the function, size has no way to know the array's original length — it only ever sees a pointer to the first element, which is why array length must always be passed as a separate parameter in C.
void printArray(int arr[], int size) { // arr is really just int*, size info is LOST
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
}
int numbers[5] = {1, 2, 3, 4, 5};
printArray(numbers, 5); // must pass the length separately — the array itself can't tell youThe real danger: buffer overflows
strcpy has no idea how big dest actually is — if source is longer than dest's capacity, strcpy happily writes past the buffer's end anyway, corrupting whatever memory happens to sit right after it. This exact class of bug has historically been one of the most common, serious sources of real security vulnerabilities in C programs.
char dest[5];
char *source = "this string is way too long for dest";
strcpy(dest, source); // UNDEFINED BEHAVIOR — writes far past dest's 5 bytes
// safer alternative, bounded by the destination's actual size:
strncpy(dest, source, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // strncpy doesn't guarantee null-termination either