I thought string literal were read only? [duplicate] - c++

This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Closed 1 year ago.
char* a = "string"; /*"string" is a string literal, thus modifying
value isn't allowed, but then why */
char b[] = "string1"; /*"string1" is
also a string literal but why modification of this is allowed? */
a[1] = 's'; //this is not allowed b[1] = 'p'; //this is allowed
Why can char array be modified when it is clearly pointing to a string literal?

when it is clearly pointing to a string literal?
No. Given char b[] = "string1";, b is not a pointer pointing to the string literal, but a char array containing copy of "string1". The modification on the string literal leads to UB, but modification on the char array is fine.
String literals can be used to initialize character arrays. If an array is initialized like char str[] = "foo";, str will contain a copy of the string "foo".
BTW char* a = "string"; is not allowed since C++11; you have to write it as const char* a = "string";.

Related

understand how char works in c++ [duplicate]

This question already has answers here:
What happened when we do not include '\0' at the end of string in C?
(5 answers)
What is the difference between char s[] and char *s?
(14 answers)
Why do string literals (char*) in C++ have to be constants?
(2 answers)
Closed last year.
I am a C++ newbie. Although many similar questions have been asked and answered, I still find these concepts confusing.
I know
char c='a' // declare a single char c and assign value 'a' to it
char * str = "Test"; // declare a char pointer and pointing content str,
// thus the content can't be modified via point str
char str1[] = "Test"; // declare a char array str1 and assign "Test" to it
// thus str1 owns the data and can modify it
my first question is char * str creates a pointer, how does char * str = "Test"; work? assign a string literal to a pointer? It doesn't make sense to me although it is perfectly legal, I think we can only assign an address to a pointer, however "Test" is a string literal not an address.
Second question is how come the following code prints out "Test" twice in a row?
char str2[] = {'T','e','s','t'}; // is this line legal?
// intializing a char array with initilizer list, seems to be okay to me
cout<<str2<<endl; // prints out "TestTest"
why cout<<str2<<endl; prints out "TestTest"?
char * str = "Test"; is not allowed in C++. A string literal can only be pointed to by a pointer to const. You would need const char * str = "Test";.
If your compiler accepts char * str = "Test"; it is likely outdated. This conversion has not been allowed since C++11 (which came out over 10 years ago).
how does char * str = "Test"; work?
String literals are implicitly convertible to a pointer to the start of the literal. In C++ arrays are implicitly convertible to pointer to their first element. For example int x[10] is implicitly convertible to int*, the conversion results in &(x[0]). This applies to string literals, their type is a const array of characters (const char[]).
how come the following code prints out "Test" twice in a row?
In C++ most features related to character strings assume the string is null terminated, which is implied in string literals. You would need {'T','e','s','t','\0'} to be equivalent to "Test".

In code blocks, Strcpy does not work when I declare a string using char * string but works when I declare it as char string[ ] [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 2 years ago.
#include <stdio.h>
#include <string.h>
int main()
{
char t1string[] = "test";
printf("First String value is %s\n", t1string);
strcpy(t1string, "lgs");
printf("Modified First String value is %s\n", t1string);
char * t2string = "test";
printf("Second String value is %s\n", t2string);
strcpy(t2string, "lgs");
printf("Modified Second String value is %s\n", t2string);
return 0;
}
Looking at the above pair of strcpy usage, I am trying to understand why the strcpy used in the second instance does not work, or is it something specifically wrong (with either my beginner level understanding or code blocks)? Or is it just telling me I am stupid for not simply doing t2string = "lgs";?
Whenever you see a string literal such as "test" in C, that is a const char[5] array which decays for most all purposes into const char *, aka a pointer to a constant character array. The letters 't', 'e', 's', 't' cannot be changed. They are stored in the same area of the program as the program instructions. Those cannot be changed either.
When you declare an array like char s[] = "test"; the constant characters "test" are copied into the array s, exactly as if you had called memcpy(s, "test", 5); From their new location in s they can be modified.
As a backward compatibility support C allows creating char * pointers to const char * arrays. But your program will still crash if you attempt to write into that constant array.

Convert char to array of chars [duplicate]

This question already has answers here:
c++ array assignment of multiple values
(4 answers)
Closed 5 years ago.
I'm doing something like that:
char* test = "HELLO";
char* test2[6] = test; //
But it is not working, how can I achieve that?
You can't copy arrays in C++, at least not without a little help. In this case the function you need is strcpy
char* test = "HELLO";
char test2[6];
strcpy(test2, test);
Also note that an array of chars is char[] not char*[] (which is an array of char pointers).
You can only initialize an array with a string literal:
8.5.2 Character arrays [dcl.init.string]
1 An array of narrow character type (3.9.1), char16_t array, char32_t array, or wchar_t array can be initialized
by a narrow string literal, char16_t string literal, char32_t string literal, or wide string literal,
respectively, or by an appropriately-typed string literal enclosed in braces (2.13.5). Successive characters of
the value of the string literal initialize the elements of the array. [ Example:
char msg[] = "Syntax error on line %s\n";
I don't know the rationale for this but I'll take a guess and say that that it is meant to guarantee that direct initializations do not overflow the array (when the size is specified).

Replacing characters in C++ Pointer Character string? [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 9 years ago.
Suppose I have this in C++:
char *p = "Apple";
I can't do this:
p[1] = 'w';
But why can I do this?
p = "OrangeTorange";
As p points to constant string literal so if you do: p[1] = 'w'; then you are trying to modifying string literal that is read only constant and its illegal operation (Undefined behavior).
Whereas in expression p = "OrangeTorange"; you modify value of p variable that is pointer to a char. And assigning new address value to p is a valid operation, now p start pointing to new string literal.
To add further, Suppose if p points an array then p[1] = 'w'; is not a invalid operation consider below example code:
char str[] = "Apple";
char* p = str; // p points to a array
p[1] = 'w'; // valid expression, not str[1] = 'w' is well valid.
p = "OrangeTorange"; // is valid
// str = "OrangeTorange"; is NOT valid as `str` is not a pointer but array name
Here both operations asked are valid!
Note: Two declarations char *str and char str[] are different. To understand it read: What does sizeof(&arr) return?
p[1] = 'w' is attempting to modify a string literal, which is illegal. p = "OrangeTorange" is just assigning a different string literal to p, which is fine.
You can't modify the original string because it's read-only data. You can modify the pointer to point to a different string because the pointer is modifiable. That is, p = "OrangeTorange" is not modifying the original string, only changing where the pointer p points to.

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

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.