2

In case 1 the output is blank when I initialize a string like this:

 #include <iostream>
 #include<string>

 using namespace std;
 //CODE 1
 int main()
 {
    string s="hello" + 'c';
    cout<<s<<endl;
    return 0;
 }

but when I write it this way it works fine:

 #include <iostream>
 #include<string>

 using namespace std;
 //CODE 2
 int main()
 {
     string s="hello";
     char k='c';
     s+=k;
     cout<<s<<endl;
     return 0;
 }

Now I am confused as in another question asked on stack overflow it says that there is no difference between string and std::string when namespace std is used, those answers go by saying that -> There is no functionality difference between string and std::string because they're the same type std::string vs string in c++ whereas the answers provided for this question are pointing differences:

compiler is g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)

Community
  • 1
  • 1

5 Answers5

6

When you have

string s="hello" + 'c';

It's equal to

string s=("hello" + 'c');

With ASCII encoding it's the same as

string s=("hello" + 99);

which is the same as

string s=(&"hello"[99]);

That is, you get a pointer to the 100:th element of the string "hello", which only have six elements (don't forget the terminator).

Going out of bounds leads to undefined behavior.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Please create your answer first and then post, don't edit thousand times! – bkausbk Mar 13 '17 at 13:23
  • You never win FGITW by doing that ;) – Borgleader Mar 13 '17 at 13:23
  • @bkausbk Answering (or commenting) is an iterative process, just like programming in general... :) – Some programmer dude Mar 13 '17 at 13:23
  • @Someprogrammerdude Indeed it is but not that way! To post only to be the first and then editing the post each minute and add line for line is really a bad behavior. If I had something to say here I would lock such posters for say 1 hour not being able to post anything. – bkausbk Mar 13 '17 at 13:27
  • `'c'` has ASCII value `99`, not `93`. – Peter Mar 13 '17 at 13:28
  • @bkausbk: Rubbish. The goal of this site is to build a credible set of questions and answers. The answerer's behaviour here is consistent with that. Edits are encouraged. This answer is probably superior to mine (although I prefer my answer as I don't mention ASCII so find my meagre +1 to be irksome). Have an upvote. – Bathsheba Mar 13 '17 at 13:29
  • @bkausbk It was a long time since I cared about being first. I *knew* I wasn't the first as I saw notifications about other answers when I started writing. It's just refinement. – Some programmer dude Mar 13 '17 at 13:29
  • @Someprogrammerdude please clarify how can I count those 6 elements since 's.size()' is returning only 5. –  Mar 13 '17 at 13:30
  • `size()` is defined by the C++ standard to **not** include the nul-terminator. – Bathsheba Mar 13 '17 at 13:31
  • @infinite String literals in C++ (like `"hello"`) are actually *arrays* of characters. More importantly they are *zero-terminated* arrays of characters. So for a string with five characters there is a sixth character for the terminator. Try printing e.g. `sizeof("hello")`. The terminator is not normally counted when getting the length of the string (with `std::string::size` or using `strlen`). – Some programmer dude Mar 13 '17 at 13:32
  • @Someprogrammerdude when I tried to do it like: 'string s="hello"; ' and then used sizeof(s), the output was 8 but when I used sizeof("hello") it gave 6. Is it because in the first case it returned size of the pointer? –  Mar 13 '17 at 13:35
  • 2
    `sizeof(s)` is the same as `sizeof(std::string)` which is about as useful as a trapdoor in a canoe. `sizeof("hello")` is `sizeof(const char[6])` which is `sizeof(6 * char)` which is `6 * sizeof(char)` which is 6, as the standard specifies `sizeof(char)` to be 1. – Bathsheba Mar 13 '17 at 13:36
  • @infinite You should not generally use `sizeof` on objects, it doesn't get the size of contained data but of the actual object itself and its member variables. – Some programmer dude Mar 13 '17 at 13:37
  • 1
    @Bathsheba But how else would we let the water out? ;) – Some programmer dude Mar 13 '17 at 13:37
  • @Someprogrammerdude I have edited the question can you please re-look and clarify my doubt. –  Mar 13 '17 at 14:03
  • 1
    @infinite That is a completely different matter, and is about namespaces and what happens when you pull in *symbols* from another namespace. The linked question doesn't mean "strings" in the general case, but simply the `std::string` class being pulled into the current namespace as `string`. – Some programmer dude Mar 13 '17 at 14:21
3

Because "string" is not a std::string but a const char*, and a pointer plus a number (a character is "just" a number) uses pointer arithmetic, so after your addition, you'll get a const char* which points possibly to garbage memory after your string literal.

The second example works because in this case, s is a std::string which has a operator += for char and does not use pointer arithmetic.

tkausl
  • 13,686
  • 2
  • 33
  • 50
3

The codes are not the same. In

string s="hello" + 'c';

"hello" is not a std::string. It is a string literal and has the type of const char[N]. When you add a character to it to the array decays to a pointer and you are doing pointer arithmetic. That arithmetic is going past the end of the string literal so it is undefined behavior.

In order to get the first code to act like the second example you need to make "hello" a string. You can use a user defined literal for std::string like

string s = "hello"s + 'c';

or just use a constructor call like

string s = std::string("hello") + 'c';
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • I have edited the question can you please clarify it further. –  Mar 13 '17 at 14:05
  • @infinite We are saying `"hello"` is not a string/std::string. – NathanOliver Mar 13 '17 at 14:10
  • then what it is? and why even bother using the 'type' as string for initialization - can you give me some reference text for exact clarification? Thanks in advance –  Mar 13 '17 at 14:14
  • This answer is crystal clear. You're better off researching "string literals in C++" – Bathsheba Mar 13 '17 at 14:15
  • @infinite I tell you right in my answer what it is. It is a `const char[N]`. What people call a c style string or just c string. – NathanOliver Mar 13 '17 at 14:16
  • @NathanOliver what I had always in mind regarding c style string was that it is something like this 'char c[]="hello" ' but I thought that when I have used the word 'string' it would be different. –  Mar 13 '17 at 14:20
  • @infinite Not really. in `string foo = "something";` ,`"something"` is not a `std::string`. It is a *string*(c string) literal (`const char[N]`). It gets copied into the `string` `foo`. – NathanOliver Mar 13 '17 at 14:22
  • @NathanOliver is there any way it can be done without c string literal? is it by defining it with default constructor ' string s;' –  Mar 13 '17 at 14:23
  • 1
    @infinite Like I said in my answer use `"hello"s` which makes it a `std::string`. – NathanOliver Mar 13 '17 at 14:28
  • @NathanOliver just one more thing, how is "hello"s working (I have never seen anything like that). –  Mar 13 '17 at 14:41
  • @infinite see: http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s – NathanOliver Mar 13 '17 at 14:54
  • `"hello"s` producing a `std::string` is a feature of C++14. It's a fair bet that someone who doesn't know that a string literal (like `"hello"`) is represented as an array of `char` and not as a `std::string` will not have caught up on all the new features that C++14. – Peter Mar 15 '17 at 10:27
1

The expression "hello" + 'c'; is adding a char type to a const char[6] type, with an obscure result. Formally the first argument decays to a const char* pointer, and c is added to that pointer using the normal rules of pointer arithmetic. The behaviour is probably undefined, since the numeric value of c is, in all encodings I've ever come across, a value greater than 6, so you end up attempting to index an element outside the const char array "hello".

In the second version, you are exploiting the overloaded += operator of the std::string class taking a char as an argument, and the character c is concatenated to that string.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Hi, I have edited the question so can you please clarify it further? –  Mar 13 '17 at 14:06
  • There's no difference between the type of `s` generated with `std::string s;` and `using namespace std; string s;`. The former should be preferred though due to the namespace polluting effects of the latter. – Bathsheba Mar 13 '17 at 14:14
0

"hello" + 'c' gives a pointer past the end of "hello" (e.g. assuming an ASCII character set, 'c' has the numeric value 99, and "hello" + 99 gives a pointer to a memory location that is 99 characters past the 'h' in "hello").

Using such a pointer to initialise an std::string gives undefined behaviour.

The "CODE 2" works std::string has an operator+=() that accepts a char, and appends it to the end of the string.

Peter
  • 35,646
  • 4
  • 32
  • 74