0

In the past i've been using Visual Studio 2010/2013/2015 and this syntax was possible :

char* szString = "This works!";

I've decided to step on and change my lifestyle of coding towards Linux, as I have installed g++ and have SlickEdit as my IDE.

It seems like that sentence doesn't work anymore. Can anyone please state why?

This works however :

char strString[] = "This works!";

The error is something with c++11.

Does anyone have an idea why this happens? Not how to fix it, cause in my workspace there isn't any way to install a c++11 compiler, i'm just curious if it has to do with something on the background on how the compiler works. What I do know about the first line of code, is that it creates a constant variable on the stack and creates a new pointer setting itself towards that ESP's value, but on the second one it counts the amount of letters on the constant variable and then sets a null terminator in the end as a result.

Oh and one more thing -> There seems to be a difference also in the way the first one is set in GCC/GPP, as the first type is {char*&} and the second one is {char(*)[12]}, any explanation on that too? Thanks!

Noam Rodrik
  • 552
  • 2
  • 16
  • 2
    `const char* szString = "This works!";` should fix your issues. – πάντα ῥεῖ Jul 10 '16 at 16:56
  • That isn't possible however, because I need it for my functions my project without a constant value. – Noam Rodrik Jul 10 '16 at 16:57
  • I don't get it why I get downvoted for asking this question If it has do to with the gcc compiler or something otherwise... – Noam Rodrik Jul 10 '16 at 16:58
  • 2
    _"because I need it for my functions my project without a constant value"_ Then you did it wrong from the beginning, or you have to use ugly casts when interacting with legacy code. – πάντα ῥεῖ Jul 10 '16 at 16:58
  • That other guy -> No, I want to unit test with buffers and putting constant variables as my input will help me unit test. – Noam Rodrik Jul 10 '16 at 17:00
  • 4
    I think the non-const char pointer to literal was deprecated in C++11 standard because any attempt to write to it was an undefined behaviour - but I am not sure. – Marian Spanik Jul 10 '16 at 17:01
  • 1
    thanks :), anyway I'm not who downvoted in case you thought so :( – niceman Jul 10 '16 at 17:02
  • 2
    by the way to mention "that other guy" just put at sign(@) and his name will appear :) – niceman Jul 10 '16 at 17:04
  • @Dreggman45 The downvote(s) are most likely because you are talking about some "error" without putting the actual error message in the question. This is bad style, because people can only guess what the actual problem here is. Help people answer your question by giving as much detail as possible and as few details as neccessary—this includes verbatim (not re-typed) error messages. – Jonas Schäfer Jul 10 '16 at 17:18

2 Answers2

6

When you write the literal "text", that text will be included somewhere the compiled program image. The program image is usually placed in write-protected memory on modern operating systems for security reasons.

char* someString = "text"; declares a pointer to the string in your probably-write-protected program image. The ability to declare this pointer as non-const was a feature included until C++11 to maintain source compatibility with C. Note that even though someString is not a pointer-to-const, any attempt to modify the value that it points to will still result in undefined behavior. This backwards compatibility feature was removed in C++11. someString must now be declared as pointer-to-const: const char* someString = "text";. You can cast the const away, but attempting to write to the value pointed to will still result in undefined behavior the same as any const value you cast to non-const.

char someString[] = "text"; works differently. This copies the string "text" from your program's code memory into an array located in data memory. It's similar to

char someString[5];
strcpy(someString, "text");

Since someString is an array in your program's data memory, it's fine to write to it, and it doesn't need to be const-qualified.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
2

According to the standard: Annex C (Compatability)

C1.1 Subclause 2.14.5:

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.

And indeed, the C++ standard 2.14.5.8 says:

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. 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

This is also allows such strings get various special treatment: the compiler/linker can choose to eliminate duplicates of a string across compilation units, (string pooling in msvc terms), it can store them in the data section and read only memory.

2.14.5.12

Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementationdefined. The effect of attempting to modify a string literal is undefined.

The char* x = "hello world"; is a throw-back to C++'s inheritance from early C. Visual Studio supports it because of the heavy baggage in their own libraries.

Community
  • 1
  • 1
kfsone
  • 23,617
  • 2
  • 42
  • 74