Under most circumstances, an expression of type "N-element array of T
" will be converted ("decay") to an expression of type "pointer to T
", and the value of the expression will be the address of the first element of the array.
The exceptions to this rule are:
- when the array expression is the operand of the
sizeof
or unary &
operators;
- when the array expression is a string literal used to initialize another array in a declaration (thus, the
"welcome back "
string literal used to initialize c
is not converted to a pointer expression; instead, the contents of the string literal are copied to c
).
When you call
len=strlen1(c);
the expression c
is converted from type "14-element array of char
" to "pointer to char
", and this pointer expression is what actually gets passed to strlen1
.
In the context of a function parameter declaration, T a[N]
and T a[]
are treated the same as T *a
; a
is declared as a pointer to T
, not an array of T
. This makes sense, since a function cannot receive an array expression as a parameter; it will have been converted to a pointer before being passed to the function.
then why it prints the whole array
That's how the %s
conversion specifier works; it tells printf
to start printing the sequence of characters beginning at the address specified by s
until it sees a 0-valued byte.
its size is only 8
The type of the expression s
is char *
, so sizeof s
is equivalent to sizeof (char *)
(that is, the size of a pointer to char
), so what you're displaying is the number of bytes required to store a pointer value, not the size of the string that s
is pointing to.
Here's a memory map of how things play out on my platform, which may help understand some of these concepts:
Item Address 00 01 02 03
---- ------- -- -- -- --
"welcome back " 0x400c89 77 65 6c 63 welc
0x400c8d 6f 6d 65 20 ome.
0x400c91 62 61 63 6b back
0x400c95 20 00 25 64 ..%d
c 0x7fffa9c401a0 77 65 6c 63 welc
0x7fffa9c401a4 6f 6d 65 20 ome.
0x7fffa9c401a8 62 61 63 6b back
0x7fffa9c401ac 20 00 00 00 ....
len 0x7fffa9c401bc 00 00 00 00 ....
s 0x7fffa9c400e8 a0 01 c4 a9 ....
0x7fffa9c400ec ff 7f 00 00 ....
p 0x7fffa9c40128 a0 01 c4 a9 ....
0x7fffa9c4012c ff 7f 00 00 ....
This is the state of things at the entry to strlen1
.
The string literal "welcome back "
is stored starting at address 0x400c89
. The character array c
is stored starting at address 0x7fffa9c401a0
. The pointer object s
is stored starting at address 0x7fffa9c400e8
and contains the address of the array object c
(x86 is little-endian, so it reads from least-signficant byte to most-significant byte). The object s
is only 8 bytes wide, which is why you got 8
as output for sizeof(s)
.
You should not use the %d
format specifier to print a value of type size_t
(which is what sizeof
returns). If you're using C99 or later, use %zu
; if you're using C89, use %lu
and cast the value to unsigned long
:
printf( "size of s=%zu\n", sizeof s ); // C99 or later
printf( "size of s=%lu\n", (unsigned long) sizeof s ); /* C89 */