To answer what exactly happens I want firstly show what your array initializations do. Your array initializer lists are incomplete, there are missing elements as the size is greater than the list. That will result in zero initialization for the missing elements.
1. char cr[3]
array:
char cr[3] = { 'a', 'b' };
will lead to:
character represantation == decimal representation
-+----+----+----+----+----+----+- -+----+----+----+----+----+----+-
| | a | b | \0 | | | | | 97 | 98 | 0 | | |
-+----+----+----+----+----+----+- -+----+----+----+----+----+----+-
^~~~ ^~~~
| char | char
cr cr
The printf()
function is defined as: int printf( const char* format, ... );
.
That means it takes a char
pointer and doesn't change the elements that are pointed to.
If you now pass the cr
array to the printf()
function the array name will decay to a pointer. The printf()
function interprets the format
parameter as null terminated character array which is called a C-string. Your cr
array is a null terminated C-string as it consists of { 'a', 'b', '\0' }
. That means the printf()
function can successfully print the string "ab"
to stdout.
2. int ar[3]
array:
int ar[3] = { 1, 2 };
will lead to:
-+----+----+----+----+----+----+-
| | 1 | 2 | 0 | | |
-+----+----+----+----+----+----+-
^~~~
| int
ar
For now you see no great difference (just type and content) in contrast to the 1st case. But now you're passing the ar
array to the printf()
function. The array name will decay to an int*
and is implicitly casted to const char*
(this will bring you the compiler warning you've got). If the printf()
function now dereferences the memory it looks like the following (assuming that an int
consists of 4 bytes and your machine uses little endian memory representation):
-+----+----+----+----+----+----+----+----+----+----+----+----+----+-
| | 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-+----+----+----+----+----+----+----+----+----+----+----+----+----+-
^~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~
| int int int
^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~
| char char char char char char char char char char char char
ar
Instead of getting a string like "12"
printed it will consume the both left characters that are the decimal value 1 and 0 (null terminator), see diagram above. The remaining decimal values after 1 and 0 are not recognized as they are after the null terminator. Assuming your machine uses the ASCII table the decimal 1 is not a printable character leading to a garbage value printed.
Proof of concept:
To prove what I write before you can use the following function which takes the same 1st argument as printf()
, namely const char*
:
void printhexchars(const char* str)
{
while(*str)
{
printf("%03d ", *(str++));
}
/* print last character after while loop: '\0' */
printf("%03d ", *str);
}
This functions prints the integer representation of a null terminated C-string. See example with your arrays char cr[3]
and int ar[3]
on ideone.com. Of course passing the integer array to the function above will generate the same compiler warning as you already get before.
Output:
character array output using printf() : 097 098 000
Integer array output using printf() : 001 000
As you can see you get 097 098 000
which is "ab"
for your character array.
Your integer array leads to 001 000
which leads to the non printable character with a decimal value of 1.