First of all, unless your compiler documentation explicitly lists void main()
as a valid signature for the main
function, use int main(void)
instead. Under most circumstances, main
is supposed to return a value to the runtime environment (even if it's just EXIT_SUCCESS).
So let's talk about the declaration
char arr [] ="hodaya";
"hodaya"
is a string literal; it is stored as a 7-element array of char
(6 characters plus 0 terminator) such that it is allocated at program startup and held until the program exits. String literals are not meant to be modifiable, and attempting to update one results in undefined behavior (which can mean anything from your code crashing with an access violation to working as expected). You should always treat string literals as read-only and never pass them to functions that attempt to modify them (such as strcpy
, strtok
, etc.).
arr
is declared as an array of char
, and it will be initialized with the contents of the string literal "hodaya"
. The size of the array is taken from the size of the initializer (7). That declaration is roughly equivalent to:
char arr[7];
strcpy( arr, "hodaya" );
It could also be written as
char arr[] = {'h', 'o', 'd', 'a', 'y', 'a', 0 };
Same result (arr
initialized with the string "hodaya"
), slightly different syntax. In this case, no string literal is created.
Since you declared arr
local to main
(it is said to have automatic storage duration, meaning that memory will be released when the function exits), you can modify the contents of arr[0]
through arr[6]
.
Now let's talk about the declaration for ptr
.
Except when it is the operand of the sizeof
or unary &
operators, or is a string literal being used to initialize another array in a declaration, 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 in the array. The result is not an lvalue; that is, it cannot be the target of an assignment.
This is important, and the source of a lot of confusion. arr
is not a pointer; it does not contain an address. When the compiler sees arr
in most contexts, it will replace it with the address of its first element, and the type of the resulting expression will be char *
. If arr
is the operand of the unary &
operator, though, the substitution doesn't happen. The value of the expression is the same (the address of the array is the same as the address of the first element of the array), but the type of is different; instead of char *
, the type of &arr
is char (*)[7]
(pointer to 7-element array of char
).
Thus, in the declaration
char *ptr = arr;
arr
is not the operand of the unary &
operator (or any other), so the conversion rule applies, and the address of the first element of arr
is written to ptr
.
By the time you're done, your memory looks something like the following (addresses are not meant to reflect any real-world architecture):
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"hodaya" 0x40040 'h' 'o' 'd' 'a'
0x40044 'y' 'a' 0 ??
...
arr 0x7fffb220 'h' 'o' 'd' 'a'
0x7fffb224 'y' 'a' 0 ??
ptr 0x7fffb228 0x7f 0xff 0xb2 0x28
Again, arr
and ptr
only exist for the lifetime of the function main
. The string
literal "hodaya"
exists for the lifetime of the entire program.
NOTE: I compiled the example above (after fixing a few issues) on a SLES 10 box using gcc 4.1.2, and yes, it created an entry for the string literal in .rodata
, even though it's only used to initialize arr
.