Why can't I write to a string literal while I *can* write to a string object? - c++

If i define something like below,
char *s1 = "Hello";
why I can't do something like below,
*s1 = 'w'; // gives segmentation fault ...why???
What if I do something like below,
string s1 = "hello";
Can I do something like below,
*s1 = 'w';

Because "Hello" creates a const char[]. This decays to a const char* not a char*. In C++ string literals are read-only. You've created a pointer to such a literal and are trying to write to it.
But when you do
string s1 = "hello";
You copy the const char* "hello" into s1. The difference being in the first example s1 points to read-only "hello" and in the second example read-only "hello" is copied into non-const s1, allowing you to access the elements in the copied string to do what you wish with them.
If you want to do the same with a char* you need to allocate space for char data and copy hello into it
char hello[] = "hello"; // creates a char array big enough to hold "hello"
hello[0] = 'w'; // writes to the 0th char in the array

string literals are usually allocated in read-only data segment.

Because Hello resides in read only memory. Your signature should actually be
const char* s1 = "Hello";
If you want a mutable buffer then declare s1 as a char[]. std::string overloads operator [], so you can index into it, i.e., s1[index] = 'w'.

Time to confuse matters:
char s0[] = "Hello";
s0[0] = 'w';
This is perfectly valid! Of course, this doesn't answer the original question so here we go: string literals are created in read-only memory. That is, their type is char const[n] where n is the size of the string (including the terminating null character, i.e. n == 6 for the string literal "Hello". But why, oh, why can this type be used to initialize a char const*? The answer is simply backward compatibility, respectively compatibility to [old] C code: by the time const made it into the language, lots of places already initialized char* with string literals. Any decent compiler should warn about this abuse, however.

Related

modify const char * vs char * content in easy way

im realy confused about const char * and char *.
I know in char * when we want to modify the content, we need to do something like this
const char * temp = "Hello world";
char * str = new char[strlen(temp) + 1];
memcpy(str, temp, strlen(temp));
str[strlen(temp) + 1] = '\0';
and if we want to use something like this
char * str = "xxx";
char * str2 = "xts";
str = str2;
we get compiler warning. it's ok I know when i want to change char * I have to use something memory copy. but about const char * im realy confused. in const char * I can use this
const char * str = "Hello";
const char * str2 = "World";
str = str2; // and now str is Hello
and I have no compiler error ! why ? why we use memory copy when is not const and in const we only use equal operator ! and done !... how possible? is it ok to just use equal in const? no problem happen later?
As other answers say, you should distinguish pointers and bytes they point to.
Both types of pointers, char * and const char *, can be changed, that is, "redirected" to point to different bytes. However, if you want to change the bytes (characters) of the strings, you cannot use const char *.
So, if you have string literals "Hello" and "World" in your program, you can assign them to pointers, and printing the pointer will print the corresponding literal. However, to do anything non-trivial (e.g. change Hello to HELLO), you will need non-const pointers.
Another example: with some pointer manipulation, you can remove leading bytes from a string literal:
const char* str = "Hello";
std::cout << str; // Hello
str = str + 2;
std::cout << str; // llo
However, if you want to extract a substring, or do any other transformation on a string, you should reallocate it, and for that you need a non-const pointer.
BTW since you are using C++, you can use std::string, which makes it easier to work with strings. It reallocates strings without your intervention:
#include <string>
std::string str("Hello");
str = str.substr(1, 3);
std::cout << str; // ell
This is a confusing hangover from the days of early C. Early C didn't have const, so string literals were "char *". They remained char * to avoid breaking old code, but they became non-modifiable, so const char * in all but name. So modern C++ either warns or gives an error (to be strictly conforming) when the const is omitted.
Your memcpy missed the trailing nul byte, incidentally. Use strcpy() to copy a string, that's the right function with the right name. You can create a string in read/write memory by use of the
char rwstring[] = "I am writeable";
syntax.
That is cause your variables are just a pointers *. You're not modifiying their contents, but where they are pointing to.
char * a = "asd";
char * b = "qwe";
a = b;
now you threw away the contents of a. Now a and b points to the same place. If you modify one, both are modified.
In other words. Pointers are never constants (mostly). your const predicate in a pointer variable does not means nothing to the pointer.
The real difference is that the pointer (that is not const) is pointing to a const variable. and when you change the pointer it will be point to ANOTHER NEW const variable. That is why const has no effect on simple pointers.
Note: You can achieve different behaviours with pointers and const with more complex scenario. But with simple as it, it mostly has no effect.
Citing Malcolm McLean:
This is a confusing hangover from the days of early C. Early C didn't have const, so string literals were "char *". They remained char * to avoid breaking old code, but they became non-modifiable, so const char * in all but name.
Actually, string literals are not pointers, but arrays, this is why sizeof("hello world") works as a charm (yields 12, the terminating null character is included, in contrast to strlen...). Apart from this small detail, above statement is correct for good old C even in these days.
In C++, though, string literals have been arrays of constant characters (char const[]) right from the start:
C++ standard, 5.13.5.8:
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.
(Emphasised by me.) In general, you are not allowed to assign pointer to const to pointer to non-const:
char const* s = "hello";
char ss = s;
This will fail to compile. Assigning string literals to pointer to non-const should normally fail, too, as the standard explicitly states in C.1.1, subclause 5.13.5:
Change: String literals made const.
The type of a string literal is changed from “array of char” to “array of const char”.
[...]char* p = "abc"; // valid in C, invalid in C++
Still, string literal assignement to pointer to non-const is commonly accepted by compilers (as an extension!), probably to retain compatibility to C. As this is, according to the standard, invalid, the compiler yields a warning, at least...

Dynamic length of strings in C++

I've debugged some programs in C++ and I notice a difference between for instance :
char str[] = "It's a test";
But when you use string in <string> header, it seems that has a variable length and for instance, the following is allowed:
string str1 = "abcdefg";
str1 = "abc";
But this is not allowed :
char str[] = "It's a test";
str = "abc";
It won't work! What's the implementation behind that?
You can initialize an array, which is done with
char array[] = "some string literal";
but you can't assign to an array. That's just the rules of the language.
The std::string class have a special overload for the assignment operator that allows it to be assigned to.
you thought that when at first you have initialised the array of characters and another time when you use it it is not needed to initialise again! but its not true...every time you declare and initialise any array and when ever you are using it again you have to do it again! for example:
char user[] = "sci3nt15t";
char user[] = "Ender";
its good for you to have a look at a definition of string and array.
hope it helps.

C++ pointers under windows 7

whenever a value is assigned to any pointer variable that is not working under windows 7 (32 bit) environment. Program containing such a code are getting execution error.
Actually I was trying to concatenate two strings without using any library functions.
Example:
int main()
{
char *s1 = "Hello";
char *s2 = "World";
char *p;
p = s1;
while(*s1 != '\0')
s1++;
while(*s2 != '\0')
{
*s1 = *s2; // this line creating problem
s1++;
s2++;
}
*s1 = '\0'; // this line also creating problem
while(*p != '\0')
{
cout<<*p;
p++;
}
return 0;
}
You have not allocated space to write into -- that's why you're having a problem.
You've created s1 and pointed it at some read-only memory, and when you try to append, you're then writing into that region.
You could instead set p to point to some memory that a) you own (have the right to write into, not just the physical ability) and b) is large enough for the full allocation.
Your easiest way to do this will be instead to use std::string -- after all, you say you're using C++.
char *s1 = "Hello";
char *s2 = "World";
When you create s1 and s2 like this, you can't write:
*s2 = anything;
Because of string pooling s1 and s2 are immutable by default.
char *s1 = "Hello";
Here, "Hello" is a string literal, which is by definition const. s1 is a pointer to the first element of that string literal, and so points to read-only memory. You cannot change read-only memory, and so you can't change what is pointed to bys1. It would have been much more accrate and better if you had declared this as:
const char *s1 = "Hello";
In C++03, there is a special rule which allows assigning the pointer to a string literal to a non-const pointer. However that rule was removed in C++11, and your code is actually illegal now.
This is a good thing because even in C++03 there is nothing you can (legally) do with s1 that you couldn't do if it was const.
Later, you do something patently wrong:
while(*s2 != '\0')
{
*s1 = *s2; // this line creating problem
s1++;
s2++;
}
I'm not surprised that line of code is causing a problem for you -- it evokes Undefined Behavior because you are modifying read-only memory.
It looks like what you're really trying to do is create a string which is initialized with some known (unchanging) value, and then later modify the string. In order to do that, you must make a copy of the string literal. Easiest way to do that is to use std::string:
std::string s1 = "Hello";
Here "Hello" is still a string literal, but s1 is being constructed off of it. s1 is completely separate from the string literal, and now you can modify it however you wish.

String statements

Talking about strings in C++, what is the difference between the following statements: s1=s2 and strcpy (s1, s2)? Supposing that s1 and s2 are (original version: type 'char', as revised) type char *.
Given:
char s1, s2;
...
s1 = s2; // Assigns value in s2 to s1
strcpy(s1, s2); // Error detected by compiler; strcpy() takes char pointers
Given:
char *s1, *s2;
...
s1 = s2; // s1 points to the same 'string' that s2 does
strcpy(s1, s2); // the space pointed to by s1 contains the same
// characters as the space pointed to by s2.
In the second case (pointers), there are a number of caveats about making sure you have enough space allocated for the actual string - as opposed to the pointers. The triple dots indicate where there is some work to be done to ensure things are initialized.
Difference between char and char* and char* null terminated string:
At first your question asked about strcpy and char. char holds a single character. Each char has an address. The address of a char is char*
It is very common in C/C++ to use a char* to point to the first character of a null terminated character array. We consider a null terminated character array a null terminated string.
To know when the string contained inside the array ends, a null terminated character is added to the end of the string.
Null terminated strings:
const char *p = "hello";
const char *s = "world";
p = s;
Both p and s hold a memory address to the first element in the array of the string literal. When you say p = s you are simply changing what the p variable holds to be the s memory address value that s holds.
So above originally p may hold 0x94749248, and s may hold 0x84811409. And after the assignment p = s, p and s hold 0x84811409.
The actual array of characters are stored at memory address 0x84811409
strcpy:
strcpy works on char* not char. By char* I mean a pointer to the first element of an array of chars, representing a null terminated string.
The following actually copies the data into szBuffer.
char szBuffer[512];
char *p = "hello world!";
strcpy(szBuffer, p);
Nowp holds a memory address of the string literal "hello world!" and szBuffer holds its own copy of all of the characters.
szBuffer after the call to strcpy still holds the same 512 memory addresses. It's just that they have been filled with the values starting at *p.
STL strings:
strings in C++ usually refer to STL strings.
#include <string>
std::string s = "hi";
There are several things wrong with your question, I'll try and clarify.
If S1 and S2 are of type char, then they're not strings, they're single characters, not strings of characters.
For S1 & S2 to be strings, they'd need to be declared like,
char* s1 = ;
char* s2 = ;
char* S1; says that S1 is not a character, but instead will point to a location in memory, and it will interpret what ever is stored there as a character.
In classic C strings are represented as a sequence of characters in memory (stored contiguously, one beside the other). The end of the string is marked by the last character, which must be Zero (hence C strings are also called Zero Terminated Strings).
This idiom for defining strings can also be done in C++, but C++ has a specific string type declared in the Standard Template Library.
So, for the second part of your question, whats the difference between strcpy(S1, S2), and S1 = S2.
Firstly, for this question to make sense S1 and S2 must be character points (as shown in the first point).
The difference is strcpy copies the string from one memory location to another (it literally moves through each character and copies it to the other memory location) while "S1 = S2", simply gets S1 to point to the same memory location that S2 points to e.g. Sample strcpy function, NB this code may not compile
function strcpy(char *destination, char* source)
{
while(*source != 0)
{
*destination = *source; /* assign this character to destination */
destination++; /* move the destination pointer to the next location*/
source++; /* move the source pointer to the next location */
}
*destination = 0; /* put a zero terminator into destination at the end of the string */
}
}
"S1 = S2" is dangerous because if you then add some characters to the string at S2, you will see those changes in S1, because they are both pointing at the same string.
NB
strcpy expects there to be enough memory allocated at S1 to hold the contents of S2 PLUS an extra character for the Zero Terminator.
Hope this helps, if you need clarification on anything, just post a comment.
if s1 and s2 are of type char*, then
char* s1 = "Hello";
char* s2 = "World";
s1 = s2; // now s1 points to World.
now, if char s1[] = "Hello";
char s2[] = "World";
then, strcpy(s1, s2); // now s1 contains Hello .
char* s1 = "Hello";
char* s2 = "World";
then, strcpy(s1, s2); // this is undefined behaviour.
I assume you mean "s1 and s2 are type char*", since the arguments to strcpy are type char*. This is an important distinction, because it means that s1 and s2 are pointers. (That's how strings are represented in C, pointers to a series of characters)
s1 = s2 assigns s1 to point to the same location as s2. Since they both now refer to the same location, they are exactly the same string, and any change made to the string from one pointer appears when using the other pointer as well.
strcpy(s1, s2) assumes that s1 already points to a memory block at least as large as the string pointed to by s2. It copies the contents of the memory block pointed to by s2 into the memory block pointed to by s1. Afterwords, the strings s1 and s2 have the same contents, but are still two different strings in two different locations and can be modified independently.
The difference is that s1 = s2 copies pointers (to contents) and strcpy(s1, s2) copies the contents.
Let's look at the following code:
char* s1 = (char*)malloc(12*sizeof(char));
strcpy(s1, "Hello World");
s1 now points to the memory address, let's say 0x0123 with the contents of "Hello World".
char* s2;
s2 = s1;
Now s2 points to the same memory location that s1, that is 0x0123.
char* s3 = (char*)malloc(12*sizeof(char));
strcpy(s3, s1);
In this case s3 points to a distinct memory address, let's say 0x0540 and has a copy of the contents of s1, that being "Hello World".
Contents wise s1, s2 and s3 look the same. The interesting thing happens when you do the following:
free(s1);
free(s2);
free(s3);
The first call to free is valid, since the memory was properly allocated and all. The second call to free is invalid (and will probably crash you app), since the memory at 0x0123 was already freed. The third call to free is valid since the memory at 0x0540 is was not freed yet.
As you can see it depends on the distinct use. Copying the pointer is much faster than copying the contents but it needs clear definition of who is in change of the memory and a proper definition of the lifetime of the memory.
Since this question is tagged with c++, I will give the additional advice:
By default use std::string. It removes many pitfalls when using strings. Yes, it is slower but 95% of the time you will never notice and in those cases where you do, you can think of a better way to do things.
I simply want to expand on Jonathan Leffler's answer slightly.
When you do s1 = s2, the following is true:
s1[0] = 'h';
s2[0] = 'q';
s1[0] == 'q';
s2[0] == 'q';
When you use strcpy, the following is true:
s1[0] = 'h';
s2[0] = 'q';
s1[0] == 'h';
s2[0] == 'q';

How to assign a string to char *pw in c++

How to assign a string to a char* (char pointer) in C++?
char *pw = some string
For constant initialization you can simply use
const char *pw = "mypassword";
if the string is stored in a variable, and you need to make a copy of the string then you can use strcpy() function
char *pw = new char(strlen(myvariable) + 1);
strcpy(pw, myvariable);
// use of pw
delete [] pw; // do not forget to free allocated memory
If you just want to assign a string literal to pw, you can do it like char *pw = "Hello world";.
If you have a C++ std::string object, the value of which you want to assign to pw, you can do it like char *pw = some_string.c_str(). However, the value that pw points to will only be valid for the life time of some_string.
If you mean a std::string, you can get a pointer to a C-style string from it, by calling c_str. But the pointer needs to be const.
const char *pw = astr.c_str();
If pw points to a buffer you've previously allocated, you might instead want to copy the contents of a string into that buffer:
astr.copy(pw, lengthOfBuffer);
If you're starting with a string literal, it's already a pointer:
const char *pw = "Hello, world".
Notice the const again - string literals should not be modified, as they are compiled into your program.
But you'll have a better time generally if you use std::string everywhere:
std::string astr("Hello, world");
By the way, you need to include the right header:
#include <string>
I think you may want to do this:
using namespace std;
string someString;
geline(cin,someString);
char *pw = strdup(someString.c_str());
But consider doing it another way. Check out http://tiswww.case.edu/php/chet/readline/rltop.html (GNU Readline library). I don't know details about it, just heard about it. Others may have more detailed or other tips for reading passwords from standard input.
If you only want to use it for a single call for something you do not need to copy the contents of someString, you may use someString.c_str() directly if it is required as const char *.
You have to use free on pw some time later,
String must be enclosed in double quotes like :
char *pStr = "stackoverflow";
It will store this string literal in the read only memory of the program.
And later on modification to it may cause UB.