-1

I was reading on errors, where it said that it's common to use concatenation of strings to describe a process, example:

void error(string s1, string s2)
{
throw runtime_error(s1+s2);
}

This led me to play around with just adding strings together, where I found an error in my code and discovered pointers:

int main()
{
    string func = "function";
    string mesg = "Testing" + " new" + func;
    cout << mesg;
}

I looked up the error and a few sources said that "Testing" + " new" was being seen as char* + char* which can't just be added together. My main question is, why doesn't it come off as string* + string*? A minor question I had also, is about the error() function. Why bother to concatenate the strings at all when you can just make a singular string?

blueyfooey
  • 11
  • 4
  • Because it is not `string* + string*` nor `string + string`. Try this: `"Testing" + string(" new") + func;` – MikeCAT Mar 03 '16 at 07:13
  • 2
    Another quirk inherited from C is that `"Testing" " new"` **without** the `+` actually works and produces a single literal. – Bo Persson Mar 03 '16 at 07:37
  • 1
    @BoPersson: Not sure if that's a quirk. I use it as a feature when having to build longer strings. – Sebastian Mach Mar 03 '16 at 10:05

3 Answers3

4

The behavior in C++ is inherited from its C roots, and both in C and C++ a literal string is actually an array of char, and as all arrays it decays to a pointer to the first element, which in the case of an array of (read-only) characters will be char const*.


The const part is important when dealing with string literals, as all string literals are read-only.

If you define an explicit array, like

char my_string[] = "foobar";

then it's not read-only and so decays to a pointer to char, i.e. char*.


As noted by DevSolar, in C string literals are actually plain arrays of char so they decay to char*. However, they are still read-only so using e.g. const char * is still a good idea when dealing with string literals.

References for the C behavior: The C11 standard §6.4.5/6 says

For character string literals, the array elements have type char

and in /7 it says:

If the program attempts to modify such an array, the behavior is undefined.

For C++ (C++11 more specifically as that's the only one I have) the relevant part is §2.14.5 [lex.string], where /8 says

A narrow string literal has type “array of n const char

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    Also note that these days you can say `"Testing"s` to mean an actual `std::string`. – juanchopanza Mar 03 '16 at 07:17
  • 1
    "Both in C and C++ a literal string is actually an *array* of `char`..." -- There is a difference. In C a string literal it is indeed of type `char[]`, but in C++ it is actually `const char[]`. – DevSolar Mar 03 '16 at 07:30
  • Thank you, this was extremely helpful! I've definitely not gotten this far in my book, so this may sound a bit dumb, but if these all act as character string literals, what would a non-literal string be? Also, bringing up my second minor question in the original post, why even concatenate strings for error()? It just seems to complicate things. – blueyfooey Mar 03 '16 at 08:08
  • @blueyfooey The example of `my_string` in my answer is an example of a C-style string that is not a literal. A literal string is only string enclosed in double-quotes. Also note that escape-codes like `"\n"` are only parsed by the compiler in string (or single character) literals, the compiler translates all those codes into the equivalent single character in the current encoding. So for example the string `"\n"` is an array of two characters, the first being the value `10` (newline in [ASCII](http://en.cppreference.com/w/cpp/language/ascii)), and then the value `0` to terminate the string. – Some programmer dude Mar 03 '16 at 08:16
  • @JoachimPileborg I see. The char array becomes non-literal because you could treat it like a vector and manipulate it by pushing things out, or moving them around, correct? – blueyfooey Mar 03 '16 at 08:20
  • @blueyfooey A literal is just a "value" written in the code. Like 123 in `int i = 123;` or hello in `string s = "hello"`.. – deviantfan Mar 03 '16 at 09:23
3

Why does char* refer to strings?

Well, it doesn't. It is just a convention; in C it is idiomatic to consider a string (as in a piece of twine) of characters that ends with a NUL character ('\0') as a string. You can have it point to a single character too.

char c = 'a';
char *p = &c;

One of the constructors of std::string takes char* as an argument, hence the implicit conversion makes you think they are interchangeable, but they are not.

why doesn't it come off as string* + string*?

In the sub-expression "Testing" + " new", it needs to implicitly convert both character arrays to std::string to perform what you want, while " new" + func works as you expect since one of them is already a std::string the other is converted, since we have an operator+ function that takes a char* (to which the character array decays into) and std::string. While there's no operator function or a rule in the language which talks about two char arrays.

Why bother to concatenate the strings at all when you can just make a singular string?

If the error function is just what you have shown it to be, then yes, having it take a single std::string makes more sense.

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • Thank you, that makes sense. So, just for clarification purposes for myself, assuming the expression was a fragment rather than a singular word, I would still receive an error from "This is a " + "sentence" because it would still be combining two char arrays, which wouldn't be possible, am I correct? Edit: I also I have a quick question about the code you provided. Why use &? Why not just put char *p = c? – blueyfooey Mar 03 '16 at 08:02
  • Yes, you would still get an error, since the expression is invalid from the compiler's viewpoint. `c` is a `char`, while `p` is `char*` so it would be an invalid assignment, while `&c` would give `char*` i.e. a pointer to `char` pointing to the memory location of `c`, and assigning `char*` to `char*` is obviously valid. – legends2k Mar 03 '16 at 08:37
  • Would char p = c fulfill the same role then? Or would it be slightly different as p would just become c rather than pointing at the original location. – blueyfooey Mar 03 '16 at 08:49
  • Yes, `char p = c;` is valid, but it would copy the value of `c` to its location instead of pointing to `c`. – legends2k Mar 03 '16 at 08:59
  • Is there a common situation where you would prefer one method over the other? Sorry for all the questions. – blueyfooey Mar 03 '16 at 09:04
  • Well, it depends. When you need to have a copy, the latter is better, when you need to hold a reference and change the entity without owning it, a reference is better. However, references are tricky to use, so for cheap objects, copy is usually better, since it's not very costly to copy them. It's okay, questions are fine :) – legends2k Mar 03 '16 at 09:08
  • Hmmm, when you say change the entity without owning it, do you mean you could alter the char* p reference, say, in a function, and the original character c would remain unaffected? Also, for a minor question in my original post, in error(), why even bother concatenating two strings? Why not just use one string and be done with it? That seems much simpler – blueyfooey Mar 03 '16 at 09:15
  • One would alter `*p` and the changes would be reflected in `c`, since `p` _is_ a reference of `c`. See the updated answer for the minor question. – legends2k Mar 03 '16 at 09:22
0

The char* data type is a carry-over from plain C in which a "string" is conventionally expressed as a character array in which the end is the nul character (value zero in ASCII).

What you have written is not additions of two char* variables but instead calling operator+ to concatenate two instances of string objects.

C++ has a way to re-define built-in operators to work with class instances. This is called operator overloading. One common use is for string classes (plural since there are a few known common implementations of string in C++) to define operator+ to concatenate strings together.

adib
  • 8,285
  • 6
  • 52
  • 91
  • Sorry, I'm a little confused. The two string objects cannot be concatenated with operator+? Aren't strings inherently able to add on to each other? – blueyfooey Mar 03 '16 at 08:10