61

I know this is a very basic question. I am confused as to why and how are the following different.

char str[] = "Test";
char *str = "Test";
Nemo
  • 4,601
  • 11
  • 43
  • 46

8 Answers8

42
char str[] = "Test";

Is an array of chars, initialized with the contents from "Test", while

char *str = "Test";

is a pointer to the literal (const) string "Test".

The main difference between them is that the first is an array and the other one is a pointer. The array owns its contents, which happen to be a copy of "Test", while the pointer simply refers to the contents of the string (which in this case is immutable).

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • 1
    Why is `char* str` commonly used when `str` denotes a string. Isn't `str[]` better? – Nemo Sep 27 '11 at 04:00
  • Is `char *str` same as `const char * str` if both denotes constants? – Nemo Sep 27 '11 at 04:02
  • 10
    @Ajan: `str[]` is a statically sized array, which copies the string. If you need a copy -only needed if pretending to modify the string-, then the array is better. Otherwise a pointer to a literal string is preferable. – K-ballo Sep 27 '11 at 04:02
  • 7
    @Ajan: They do not both denote constant, string literals are allowed to bind to non const pointers just to support legacy C. Literals should always be refered by a const pointer to avoid potential undefined behavior. – K-ballo Sep 27 '11 at 04:03
  • 1
    Ok, that explains why I get `warning: deprecated conversion from string constant to ‘char*’` – Nemo Sep 27 '11 at 04:06
  • Would you mind updating this answer to include that `char *str = "Test";` is actually illegal starting in C++11? – NathanOliver Dec 11 '18 at 13:52
  • 1
    @K-ballo if **str** is a pointer in `char *str = "Test";` then does that mean that the literal "Test" is stored somewhere in the memory? – asn Jan 07 '19 at 09:25
  • Could you make this part of your answer bold: **The array owns its contents, the pointer simply refers to the (immutable)contents of the string** ? – DarkTrick Aug 01 '21 at 05:58
  • Why is it immutable? – dijonkitchen Jan 19 '22 at 14:01
30

The diference is the STACK memory used.

For example when programming for microcontrollers where very little memory for the stack is allocated, makes a big difference.

char a[] = "string"; // the compiler puts {'s','t','r','i','n','g', 0} onto STACK 

char *a = "string"; // the compiler puts just the pointer onto STACK 
                    // and {'s','t','r','i','n','g',0} in static memory area.
rnrneverdies
  • 15,243
  • 9
  • 65
  • 95
  • Does that apply only for microcontrollers? If not, then what's the difference b/w static memory area and stack? – asn Jan 07 '19 at 09:28
  • This would apply even if you weren't programming for microcontrollers, but were concerned about memory usage. Microcontrollers normally have less memory for the stack than say your computer. – dijonkitchen Jan 19 '22 at 14:03
  • @dijonkitchen In the first case, the array of 7 characters takes up 7 bytes of memory whereas in the second case the pointer to a character takes up 8 bytes. Does this mean that the array of characters is more favorable over the pointer case for memory-critical usages? Moreover, in the pointer case the pointer takes up memory as well as {'s','t','r','i','n','g',0}. – ConventionalProgrammer May 03 '23 at 20:09
  • I guess it would depend on what you're pointing to. If it's a string longer than 8 bytes, it'd use less memory with a pointer. And vice versa. – dijonkitchen May 04 '23 at 16:33
  • Upvote for this answer in the perspective of assembly language. – Li-Guangda Jul 18 '23 at 11:13
11

A pointer can be re-pointed to something else:

char foo[] = "foo";
char bar[] = "bar";

char *str = foo;  // str points to 'f'
str = bar;        // Now str points to 'b'
++str;            // Now str points to 'a'

The last example of incrementing the pointer shows that you can easily iterate over the contents of a string, one element at a time.

Jon Reid
  • 20,545
  • 2
  • 64
  • 95
7

One is pointer and one is array. They are different type of data.

int main ()
{
   char str1[] = "Test";
   char *str2 = "Test";
   cout << "sizeof array " << sizeof(str1) << endl;
   cout << "sizeof pointer " << sizeof(str2) << endl;
}

output

sizeof array 5
sizeof pointer 4
Luka Rahne
  • 10,336
  • 3
  • 34
  • 56
  • that is something new so when is stored in pointer that doesn't need to be terminated by NULL character? – user3995169 Sep 10 '14 at 01:11
  • 6
    @Stack Overflow ponter is stored as adress that takes 4 bytes. Longer string would return as `sizeof array 20` `sizeof pointer 4` – Luka Rahne Sep 10 '14 at 14:45
5

The first

char str[] = "Test";

is an array of five characters, initialized with the value "Test" plus the null terminator '\0'.

The second

char *str = "Test";

is a pointer to the memory location of the literal string "Test".

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • Not sure, but it's an array of 5 characters. `{'T', 'e', 's', 't', '\0'}`. – Bill Lynch Sep 27 '11 at 04:05
  • @PeterOlson you said pointer to the memory location. Does that mean ptr stores the starting address of the "Test"? One thing i know clearly pointers can only store address and "Test" is not a address. – user3995169 Sep 10 '14 at 01:09
  • 1
    @StackOverflow Yes, a pointer points to the starting address, and then you can find the string by going the the starting address (pointing to the letter `T`) and going right until the null terminator is reached. – Peter Olson Sep 10 '14 at 02:51
  • @PeterOlson Does that mean that the literal "Test" is stored somewhere in memory and terminated by '\0' and ptr pointing to 'T' of "Test"? If yes, which memory does "Test" resides in? – asn Jan 07 '19 at 09:31
4

Starting from C++11, the second expression is now invalid and must be written:

const char *str = "Test";

The relevant section of the standard is Appendix C section 1.1:

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 “array of some-integer-type” to “array of const char16_t.” The type of a char32_t string literal is changed from “array of some-integer-type” to “array of const char32_t.” The type of a wide string literal is changed from “array of wchar_t” to “array of const wchar_t.”

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.

Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
  • Suppose char* is the return type of a function `char* fun()`? Will there be any change in the specification of the return type or the returned value now? – asn Jan 07 '19 at 09:34
  • @AjaySinghNegi Definitely. You need to return a `const char*`. – Matthieu Brucher Jan 07 '19 at 09:49
2

"Test" is an array of five characters (4 letters, plus the null terminator.

char str1[] = "Test"; creates that array of 5 characters, and names it str1. You can modify the contents of that array as much as you like, e.g. str1[0] = 'B';

char *str2 = "Test"; creates that array of 5 characters, doesn't name it, and also creates a pointer named str2. It sets str2 to point at that array of 5 characters. You can follow the pointer to modify the array as much as you like, e.g. str2[0] = 'B'; or *str2 = 'B';. You can even reassign that pointer to point someplace else, e.g. str2 = "other";.

An array is the text in quotes. The pointer merely points at it. You can do a lot of similar things with each, but they are different:

char str_arr[] = "Test";
char *strp = "Test";

// modify
str_arr[0] = 'B'; // ok, str_arr is now "Best"
strp[0] = 'W';    // ok, strp now points at "West"
*strp = 'L';      // ok, strp now points at "Lest"

// point to another string
char another[] = "another string";
str_arr = another;  // compilation error.  you cannot reassign an array
strp = another;     // ok, strp now points at "another string"

// size
std::cout << sizeof(str_arr) << '\n';  // prints 5, because str_arr is five bytes
std::cout << sizeof(strp) << '\n';     // prints 4, because strp is a pointer

for that last part, note that sizeof(strp) is going to vary based on architecture. On a 32-bit machine, it will be 4 bytes, on a 64-bit machine it will be 8 bytes.

Tim
  • 8,912
  • 3
  • 39
  • 57
  • 4
    You can't modify string literals, they are immutable; doing so is undefined behavior. – K-ballo Sep 27 '11 at 04:07
  • `strp[0] = 'W';` invokes undefined behaviour, because it attempts to modify a constant string. – davmac Sep 27 '11 at 04:14
  • 1
    in arrays we can modify the content but not in the case of pointer. Please fix your answer its wrong. Someone might learn wrong thing reading this @Tim – user3995169 Sep 10 '14 at 01:15
-2

Let's take a look at the following ways to declare a string:

char name0 = 'abcd';           // cannot be anything longer than 4 letters (larger causes error)
cout << sizeof(name0) << endl; // using 1 byte to store

char name1[]="abcdefghijklmnopqrstuvwxyz"; // can represent very long strings
cout << sizeof(name1) << endl;             // use large stack memory

char* name2 = "abcdefghijklmnopqrstuvwxyz"; // can represent very long strings
cout << sizeof(name2) << endl;              // but use only 8 bytes

We could see that declaring string using char* variable_name seems the best way! It does the job with minimum stack memory required.

  • `name0` here should be just a single character I believe. Right now it's probably being interpreted as an int and then downcast to a char. – mattlangford Jun 02 '21 at 21:27
  • shouldn't it be `const char* name2 = "abcdefghijklmnopqrstuvwxyz";`? My compiler gives warnings about C++ forbidding the conversion of a string constant into char*. – ConventionalProgrammer May 03 '23 at 20:21