Hi all,
can someone help knowing the difference between

char *st="myname";
char st[]="myname";

i know they both is array of charachers but the difference when dealing with them and how they are in memory ?

Thanks.

No, both are not array of characters. Only the second one is. The first one is simply a pointer to a character which happens to be the first character 'm' of "myname".
Also note that you can change characters in the second one while not in the first one as the actual string is stored in the data section in the first case, which is read-only.

Edited 2 Years Ago by tapananand

Never assign raw data directly to an uninitialised pointer. If done so, where would the pointer point to? Where will the raw data be stored? Maybe it will compile, maybe it won't. Maybe it could lead to disastrous effects. You have to make sure a pointer points to something (safe) before using it. So: char *st="myname"is plain wrong.

Anyway, a pointer variable, declared with an asterisk operator, ie: char * a;, is a variable that contains an address. This pointer still needs to be assigned, so let's say we assign st's (an array) address to it: a = st;Printing a, then, will show the address of st's first element, wherever it is in memory. By using a dereference operator (asterisk), you can access the value in the address that the pointer points to, ie: cout << *a shows st's first element.

An array is a block of memory reserved depending on the indicated size. By using the name in conjunction with an index, it's use is similar to a pointer in such that the value located in the array's first element address, offset by the index is being accessed. The main difference between the two is that arrays have fixed addresses, whereas pointers can be reassigned different addresses.

Examples:

char st[] = "myname";
char * a = st; // valid, because pointers can be assigned new addresses as values
st = a; //invalid, because array addresses are fixed

cout << *a; // outputs st[0]
a = &st[1]; // assigns address of st[1] to a
cout << *(a+1); // outputs st[2]
a = st + 3; // essentially assigns address of st[3] to a

Never assign raw data directly to an uninitialised pointer. If done so, where would the pointer point to? Where will the raw data be stored? Maybe it will compile, maybe it won't. Maybe it could lead to disastrous effects. You have to make sure a pointer points to something (safe) before using it. So: char *st="myname"is plain wrong.

Um...what? char *st="myname" is fine. The pointer is initialized and points to a string literal. The only disastrous thing involved is the read-only status of the string literal, and that's only a problem if subsequent code tries to modify it through the pointer.

Ya char *st="myname" is not a problem at all and as I pointed out earlier it is present in the data section.

Some compilers will bitch at you if you try to assign a string literal to a char* (often depending upon how you set the strictness level of type-checking for the compiler). You SHOULD use a const char* instead in such cases. The first case is a clear violation of intentional programming - do what you intend. If you INTEND for the string to be mutable, then use the char var[] = "a string" construct. You can use var as a char or const char pointer as necessary without needing to any casting.

can someone help knowing the difference between

> char *st="myname"; 
> char st[]="myname";

"myname" is a narrow string literal; in C++, A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration. - IS

So, with "myname" we have an an lvalue of type array of 7 const char. The life-time of this array is the duration of the program.

This array can be implicitly converted to a prvalue of of type “pointer to const char”; the result of the conversion is a pointer to the first element of the array. For compatibility with C code, C++98 specified:

A string literal that is not a wide string literal can be converted to an rvalue of type “pointer to char” ... [Note: this conversion is deprecated.]

C++11 simply dropped the above clause from the IS, and has this in Annex C (Compatibility):

Change: String literals made const

The type of a string literal is changed from “array of char” to “array of const char.” The type of a char16_t string literal is changed from ...

Rationale: This avoids calling an inappropriate overloaded function, which might expect to be able to modify its argument.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Syntactic transformation. The fix is to add a cast:

> char* p = "abc"; // valid in C, invalid in C ++
>         
> void f(char*) {
>    char* p = (char*)"abc"; // OK: cast added
>    f(p);
>    f((char*)"def"); // OK: cast added
> }

So char *st="myname"; is an invalid construct in C++.

const char* st = "myname" ; is valid C++; the type of st is pointer to const char, and it is initialised with the address of the first character in the literal.

With char st[]="myname";, the type of st is array of 7 char and the array is intialised with a string literal.

Successive characters of the value of the string literal initialize the elements of the array.

The array st is initiaslised as if we had written:
char st[] = { 'm', 'y', 'n', 'a', 'm', 'e', 0 };

.
Note: mainstream compilers still pass char* st = "myname" ; with just a warning.
(eg. -Wc++11-compat-deprecated-writable-strings in clang++)
http://coliru.stacked-crooked.com/a/a2c5eacd3878e838

Edited 2 Years Ago by vijayan121

Comments
Very complete! And I didn't know C++11 deprecated this construct, cool!
This article has been dead for over six months. Start a new discussion instead.