Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String Literals

Tags:

c++

I have few doubts about string literals in c++.

char *strPtr ="Hello" ;
char strArray[] ="Hello";

Now strPtr and strArray are considered to be string literals.

As per my understanding string literals are stored in read only memory so we cannot modify their values.

We cannot do

strPtr[2] ='a';
and strArray[2]='a';

Both the above statements should be illegal. compiler should throw errors in both cases.

Compiler keeps string literals in read only memory , so if we try to modify them compiler throws errors.

Also const data is also considered as readonly.

Is it that both string literals and const data are treated same way ? Can I remove constantness using const_cast from string literal can change its value?

Where exactly do string literals are stored ? (in data section of program)

like image 692
anand Avatar asked Apr 05 '09 06:04

anand


3 Answers

Now strPtr and strArray are considered to be string literals.

No, they aren't. String literals are the things you see in your code. For example, the "Hello". strPtr is a pointer to the literal (which is now compiled in the executable). Note that it should be const char *; you cannot legally remove the const per the C standard and expect defined behavior when using it. strArray is an array containing a copy of the literal (compiled in the execuable).

Both the above statements should be illegal. compiler should throw errors in both cases.

No, it shouldn't. The two statements are completely legal. Due to circumstance, the first one is undefined. It would be an error if they were pointers to const chars, though.

As far as I know, string literals may be defined the same way as other literals and constants. However, there are differences:

// These copy from ROM to RAM at run-time:
char myString[] = "hello";
const int myInt = 42;
float myFloats[] = { 3.1, 4.1, 5.9 };

// These copy a pointer to some data in ROM at run-time:
const char *myString2 = "hello";
const float *myFloats2 = { 3.1, 4.1, 5.9 };

char *myString3 = "hello";  // Legal, but...
myString3[0] = 'j';         // Undefined behavior!  (Most likely segfaults.)

My use of ROM and RAM here are general. If the platform is only RAM (e.g. most Nintendo DS programs) then const data may be in RAM. Writes are still undefined, though. The location of const data shouldn't matter for a normal C++ programmer.

like image 114
strager Avatar answered Sep 30 '22 00:09

strager


char *strPtr ="Hello" ;

Defines strPtr a pointer to char pointing to a string literal "Hello" -- the effective type of this pointer is const char *. No modification allowed through strPtr to the pointee (invokes UB if you try to do so). This is a backward compatibility feature for older C code. This convention is deprecated in C++0x. See Annex C:

Change: String literals made const The type of a string literal is changed from “array of char” to “array of const char.” [...]

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. Difficulty of converting: Simple syntactic transformation, because string literals can be converted to char*; (4.2). The most common cases are handled by a new but deprecated standard conversion:

char* p = "abc"; // valid in C, deprecated in C++

char* q = expr ? "abc" : "de"; // valid in C, invalid in C++

How widely used: Programs that have a legitimate reason to treat string literals as pointers to potentially modifiable memory are probably rare.

char strArray[] ="Hello";

The declared type of strPtr is -- it is an array of characters of unspecified size containing the string Hello including the null terminator i.e. 6 characters. However, the initialization makes it a complete type and it's type is array of 6 characters. Modification via strPtr is okay.

Where exactly do string literals are stored ?

Implementation defined.

like image 20
dirkgently Avatar answered Sep 30 '22 01:09

dirkgently


The older C and C++ compilers were purely based on low level coding where higher standards of data protection were not available, and they can not even be enforced, typically in C and C++ you can write anything you want..

You can even write a code to access and modify your const pointers as well, if you know how to play with the addresses.

Although C++ does enforce some compile level protection, but there is no protection on runtime. You can certainly access your own stack, and use its values to manipulate any data that came in const pointer as well.

That is the reason C# was invented where little higher level standards are enforced because whatever you access is reference, it is a fixed structure governing all rules of data protection and it has hidden pointer which can not be accessed and nor modified.

The major difference is, C++ can only give you compile time protection, but C# will give you protection even at runtime.

like image 22
Akash Kava Avatar answered Sep 30 '22 02:09

Akash Kava