9

Here I've two lines of code

const char * s1 = "test";
char s2 [] = "test";

Both lines of code have the same behavior, so I cannot see any difference whether I should prefer s1 over s2 or vice-versa. In addition to s1 and s2, there is also the way of using std::string. I think the way of using std::string is the most elegant. While looking at other code, I often see that people either use const char * or char s []. Thus, my question is now, when should I use const char * s1 or char s [] or std::string? What are the differences and in which situations should I use which approach?

System.Data
  • 3,878
  • 7
  • 32
  • 40
  • 2
    They don't have the same behaviour :-) the first only puts a pointer to a constant string to the stack, and the second puts the whole mutable string on the stack. – Kos Feb 22 '12 at 10:46
  • FYI) Type of unprefixed ['string literal'](https://en.cppreference.com/w/cpp/language/string_literal) such as `"abc"` is 'array of const char', i.e. `const char[N]` (N is the size of the string including the null terminator). This is true for both C and C++ at least right now. To add to Kos's comment right above, string literals have 'static storage duration'(last for the duration of the program). As the standard or [this](https://stackoverflow.com/a/349031/10027592) answer quotes. – starriet Jul 05 '23 at 23:35

7 Answers7

11
POINTERS
--------

char const* s1 = "test";  // pointer to string literal - do not modify!

char* s1       = "test";  // pointer to string literal - do not modify!
                          //   (conversion to non-const deprecated in C++03 and
                          //       disallowed in C++11)

ARRAYS
------

char s1[5]     = "test";  // mutable character array copied from string literal
                          //    - do what you like with it!

char s1[]      = "test";  // as above, but with size deduced from initialisation



CLASS-TYPE OBJECTS
------------------

std::string s1 = "test";  // C++ string object with data copied from string
                          //    literal - almost always what you *really* want
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
9
const char * s1 = "test";
char s2 [] = "test";

These two aren't identical. s1 is immutable: it points to constant memory. Modifying string literals is undefined behaviour.

And yes, in C++ you should prefer std::string.

RJHunter
  • 2,829
  • 3
  • 25
  • 30
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • Is there are reason why I often see that people use const keyword? Without the const keyword, I get the same behavior, so char * s1 = "test";. It works fine without any compiler errors ... – System.Data Feb 22 '12 at 10:51
  • 1
    @System.Data see Lightness's answer. The default conversion is deprecated now. It shouldn't be allowed IMO, but it is. It's still UB if you try to modify it. – Luchian Grigore Feb 22 '12 at 10:53
  • @System.Data: Only because you are not using adequate warnings in your build settings. That conversion from `const char*` to `char*` for string literals was allowed in old C (back when it didn't have the safety of `const` _at all_), but is gradually being phased out of C++. So, it's deprecated in C++98/C++03... and downright illegal in C++11. _It's dangerous because it makes you syntactically able to modify the data in the string, whereas in fact it's constant data._ – Lightness Races in Orbit Feb 22 '12 at 10:55
  • 5
    @System.Data: As a more general protocol, you should **always** use `const` except where you know you don't want to... not the other way around. It's a design flaw rooted in backwards compatibility that C++ names default to mutable rather than immutable. – Lightness Races in Orbit Feb 22 '12 at 10:57
3

The first one is constant, the second isn't. std::string is a class type and implements many useful functions and methods for string manipulation, making it much easier and user-friendly. The c-style 'strings' with char pointers are difficult to control, manipulate and often cause errors, but don't have the overhead the std::string has. Generally it's better to stick to the std::strings cause they're easier to maintain.

Alexander
  • 8,117
  • 1
  • 35
  • 46
3

The only difference between the two that you should care about is this:

Which one is your project already using?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
x10
  • 3,820
  • 1
  • 24
  • 32
  • There is an element of truth to this, but it's _far_ from the primary factor. – Lightness Races in Orbit Feb 22 '12 at 10:53
  • Actually, and unfortunately, it usually is the *only* factor, because you're seldom in a position to chance project policy. Yep, I'm a bit disenchanted that way. – DevSolar Feb 23 '12 at 09:33
  • 1
    Development team politics are out of the scope of this question, which is a question about a programming language. Also, if you're not given the opportunity to steer development policies then you're either very junior in a very large team, or in a bad job. (Or both.) – Lightness Races in Orbit Feb 24 '12 at 19:29
  • What I meant was - consistency is among the most valuable things in a codebase. Regardless of any personal opinion in the matter, consistency trumps even things like const correctness. – x10 Feb 27 '12 at 09:58
3

These two do not have the same behavior. s1 is a simple pointer which is initialized to point to some (usually read-only) area of the memory. s2, on the other hand, defines a local array of size 5, and fills it with a copy of this string.

Formally, you are not allowed to modify s1, that is, do something like s1[0] = 'a'. In particular, under weird circumstances, it could cause all other "test"s in your program to become "aest", because they all share the same memory. This is the reason modern compilers yell when you write

char* s = "test";

On the other hand, modifying s2 is allowed, since it is a local copy.

In other words, in the following example,

const char* s1 = "test";
const char* s2 = "test";
char s3[] = "test";
char s4[] = "test";

s1 and s2 may very well point to the same address in memory, while s3 and s4 are two different copies of the same string, and reside in different areas of memory.

If you're writing C++, use std::string unless you absolutely need an array of characters. If you need a modifiable array of characters, use char s[]. If you only need an immutable string, use const char*.

user1071136
  • 15,636
  • 4
  • 42
  • 61
0

which one to be used depends upon your requirement. Pointer offers you more flexiblity. and in some cases vulerability. Strings are a safe option and they provide Iterator support.

Rohit Vipin Mathews
  • 11,629
  • 15
  • 57
  • 112
0

Use std::string unless you know why you need a char array / pointer to char.

DevSolar
  • 67,862
  • 21
  • 134
  • 209