Please help me understand whats really happening.
Undefined behaviour!
When you do this, you've a buffer overrun:
char line[3];
strcpy(line, "Hello world");
Why is it that it displays all of "Hello world" when i declared my string to only hold 3 characters?
You're copying more than the size of the allocated array. This is undefined behaviour and thus any output is possible, including but not limited to, calling aunt Tilda, formatting your hard disk, etc. :) See here for more.
char line[3] = "Hello world";
printf("%s", line);
Here you've a buffer over-read! Refer to alk's answer on why only 3 characters would get copied to line
.
Why is it that it displays "Hel"? Shouldnt it display only "He"
No, it can display anything, again because of undefined behaviour. See what output I get on my machine:
Hel☻
This is undefined behaviour because printf
expects you to have a null-terminated string, yes, but that doesn't mean you can access beyond the size of an array i.e. you've an array like this in memory
[0] [1] [2]
-----------------------------------------------
. . . █ | █ | █ | H | e | l | █ | █ | █ | . . .
-----------------------------------------------
<-- line --->
Any thing written as █ above is an unknown value, not under your powers and thus accessing them is undefined. However, %s
in printf
expects a null-terminated string and thus, under your orders, it reads beyond what's allowed (what is allowed is just three elements till l
). In my case \0
appeared one element after l
(the smiley), while in your case it's just after l
thus appearing correct but only by luck, it may well appear 1000 elements later.
If you really want to print the char
array, which is not null-terminated, only up to the allowed limit, you could do one of these without hitting any undefined behaviours.
printf("%.3s", line); // length specified at compile-time
printf("%.*s", 3, line); // length fed at run-time
See here for further information.