Warning deprecated conversion from string constant to char * [duplicate] - c++

This question already has an answer here:
C++ warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
(1 answer)
Closed 8 years ago.
I use the cmd to compile with a .bat and g++.exe. Can someone tell me what I did wrong? I am using it to practice as I follow a tutorial on strings and arrays. Please keep in mind that I am still learning.
main.cpp: In function 'int main()':
main.cpp:6:12: warning: deprecated conversion from string constant to 'char*' [-
Wwrite-strings]
main.cpp:10:12: warning: deprecated conversion from string constant to 'char*' [
-Wwrite-strings]
main.cpp:11:12: warning: deprecated conversion from string constant to 'char*' [
-Wwrite-strings]
Press any key to continue . . .
My Code:
using namespace std;
#include <iostream>
int main() {
//Asterisk to make the variable an array. Takes 8 bytes of memory (8 characters including spaces).
char *a = "hi there";
//Inside square brackets is the number of bytes of memory to use. More consumtion of resources
char b[500]="hi there";
//For a new line, type \n. For a tab, type \t.
char *c = "Hi There\nFriends!";
char *d = "\t\tHi There Friends!";
//endl will end the line.
cout << a;
cout << b << endl;
cout << c << endl;
cout << d << endl;
}

Strings between double quotes are string literals. They are arrays of char which are not to be modified (attempting to modify them invokes undefined behavior). That's why you should declare a pointer pointing to a string literal as const char * - this way, if some code erroneously tries to write/modify a character in the literal, the compiler will have a chance to catch this error.

Related

why char * works with const only [duplicate]

This question already has answers here:
What is the type of string literals in C and C++?
(4 answers)
Closed 6 months ago.
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
#define nline "\n"
int main(){
//const char *p="hello world";
// court<<p;
char *p="hello world";
cout<<p;
}
C:\Users\Dell\AppData\Roaming\Sublime Text\Packages\User\cses2.cpp: In function 'int main()':
C:\Users\Dell\AppData\Roaming\Sublime Text\Packages\User\cses2.cpp:7:10: warning: ISO C++ forbids converting a string constant to 'char' [-Wwrite-strings]*
char *p="hello world";
^~~~~~~~~~~~~
"hello world" is a const char[12]. A c-array of 12 constant (!) characters (note that one is for the null terminator).
In early C++ standards it was allowed to get a char * to a string literal due to compatibility with C. Though, it was nevertheless forbidden to actually modify the characters of the string literal via the char *.
This changed in C++11 and since then string literals have proper const correctness.
If you do want a string that can be modified, then use a std::string. Note that the pointer you obtain from the literal is not a string, its just a pointer to a (non-modifiable) c-string. If you want a string rather than a pointer to one, you need to use a string.

error: ISO C++ forbids converting a string constant to ‘char*’ [duplicate]

This question already has answers here:
Why is conversion from string constant to 'char*' valid in C but invalid in C++
(4 answers)
Deprecated conversion from string literal to 'char*' [duplicate]
(3 answers)
Closed 4 months ago.
I'm trying to run the following code, taken from "Object Oriented Programming with C++" by Balagurusamy (8th edition):
#include <iostream>
#include <cstring>
using namespace std;
class String
{
char *name;
int length;
public:
String()
{
length = 0;
name = new char[length+1];
}
String(char *s)
{
length = strlen(s);
name = new char[length+1];
strcpy(name,s);
}
void display(void)
{cout<<name<<"\n";}
void join(String &a, String &b);
};
void String :: join(String &a, String &b)
{
length = a.length + b.length;
delete name;
name = new char[length+1];
strcpy(name, a.name);
strcat(name, b.name);
};
int main()
{
char *first = "Joseph ";
String name1(first), name2("Louis"), name3("Lagrange"), s1,s2;
s1.join(name1, name2);
s2.join(s1,name3);
name1.display();
name2.display();
name3.display();
s1.display();
s2.display();
return 0;
}
When I compile with g++, I run into the following log:
g++ -Wall -Werror -Wextra constructors_with_new.cpp -o constructors_with_new.o
constructors_with_new.cpp: In function ‘int main()’:
constructors_with_new.cpp:45:15: error: ISO C++ forbids converting a string constant to ‘char*’ [-Werror=write-strings]
45 | char *first = "Joseph ";
| ^~~~~~~~~
constructors_with_new.cpp:47:28: error: ISO C++ forbids converting a string constant to ‘char*’ [-Werror=write-strings]
47 | String name1(first), name2("Louis"), name3("Lagrange"), s1,s2;
| ^~~~~~~
constructors_with_new.cpp:47:44: error: ISO C++ forbids converting a string constant to ‘char*’ [-Werror=write-strings]
47 | String name1(first), name2("Louis"), name3("Lagrange"), s1,s2;
| ^~~~~~~~~~
cc1plus: all warnings being treated as errors
Then I found the following answer
Why is conversion from string constant to 'char*' valid in C but invalid in C++
and to make it work, I modified the above code
to receive a pointer to const char inside the 2nd constructor (String(char const *s))
inside main(), by changing the initialization of the first name "Joseph", from char * first to char const * first, as suggested by Jeremy Coffin in the answer to the provided link
In this way, it compiles without problems with the following output
Joseph
Louis
Lagrange
Joseph Louis
Joseph Louis Lagrange
What I wonder is whether this is the best way to fix this problem, or if you recommend a different way (maybe another that doesn't need to enter a pointer to a const of type char).
Best,
Stefano
As the comments indicate, you need to use const char*, not char*. It looks like the book is badly out of date.
In C++, a string literal is of type const char[N], where N is the number of characters in the literal plus one for the terminating '\0'.
I was able to make your code compile and run by making the following changed:
Change the constructor for String from
String(char *s)
to
String(const char *s)
Change the declaration of first from
char *first = "Joseph ";
to
const char *first = "Joseph ";
Remove the extraneous semicolon at the end of String::join.
Also, the code would be a lot more legible with proper indentation.
A string literal in C++ is by default a const char*. That's why you are seeing these warnings where you are trying to assigning a const char* to a char*.
You can simply remove these warnings by casting away the constness of the char*. You can achieve this by using const_cast<char*>
Eg:
char *first = const_cast<char*>("Joseph ");
String name1(first), name2(const_cast<char*>("Louis")), name3(const_cast<char*>("Lagrange")), s1,s2;
This should remove your warning.
Edit: This is not the best advice. My answer is only meant to explain how you can cast away const-ness of the string literal and in no way promotes it. The constness of string literal exists for a reason.

Please explain char* return type in C++ [duplicate]

This question already has answers here:
cout << with char* argument prints string, not pointer value
(6 answers)
Closed 2 years ago.
I have written a simple C++ code, and its working fine. But I don't know how it is working. I am just replacing "l" with "r" using myfun().
The return type of myfun() is char*. If I am returning &(str[0]), that is, only the address of the first element of the array, then why is it printing the complete string "herloworld"? Please explain what return &(str[0]); is doing.
#include <iostream>
using namespace std;
char* myfun(char str[])
{
str[2] = 'r';
return &(str[0]);
}
int main()
{
char str[] = "helloworld";
char* word;
word = myfun(str);
cout << word;
}
The operator << is overloaded for the type char * such a way that it expects that the used pointer of the type char * points to the first character of a string.
So the operator outputs all characters of the passed string until the zero character '\0' is encountered.
Also pay attention to that arrays used in expressions with rare exceptions are converted to pointers to their first elements.
So this call
word = myfun(str);
is equivalent to
word = myfun( &str[0]);
On the other hand, a function parameter having an array type is implicitly adjusted to pointer to the element type.
So this function declaration
char* myfun(char str[]);
is equivalent to the following declaration
char* myfun(char *str);
The both declarations declare the same one function.
And within the function instead of this return statement
return &(str[0]);
you could write
return str;
Correspondingly in main you could write
cout << myfun(str);
without declaring and using the intermediate pointer word.

C++, char* string modification [duplicate]

This question already has answers here:
Program crashes when trying to set a character of a char array
(5 answers)
Closed 5 years ago.
I am new to C++.
I have a program:
#include <iostream>
int main()
{
char* str = "Test";
*str = 'S';
}
The question is, why *str = 'S' crashes the program?
As far as I know str must be pointing to the first character of the string (well, char array), so in theory I should be able to modify it.
Is it because the memory is read-only for defined constant values?
I am using gcc 5.3.0.
why *str = 'S' crashes the program?
Because you're not allowed to modify string literals. The C++ standard allows them to be stored in read-only memory.
In fact, if you enable compiler warnings, you get:
prog.cc:5:16: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
char* str = "Test";
^~~~~~
Always use const char* when pointing to string literals:

C++ Char Initialization Allowed With Multiple Characters [duplicate]

This question already has answers here:
What do single quotes do in C++ when used on multiple characters?
(5 answers)
Closed 6 years ago.
During learning about C++ by reading a book I have seen this (for me) strange line of code.
char ch('AB'); // Or char ch = 'AB';
It is strange for me because I don't get that you can assign to a char multiple "letters" without getting any exception.
cout << "Characters in ch: " << ch << endl; // Output B
Why does this work? And how is it working internally? Is it only saving the last character and ignoring the other ones?
It's called a multicharacter literal which are completely valid C++:
Multicharacter literal, e.g. 'AB', has type int and implementation-defined value.
[...]
Many implementations of multicharacter literals use the values of each char in the literal to initialize successive bytes of the resulting integer, in big-endian order, e.g. the value of '\1\2\3\4' is 0x01020304.
It is strange for me because I don't get that you can assign to a char multiple "letters" without getting any exception.
You should see it as a type conversion (demo):
#include <iostream>
using namespace std;
int main()
{
{
int i = 'abcd';
char c = i; // cast form int to char -> c == 'd'
cout << c; // prints 'd'
}
{
char c = 'abcd'; // cast form int to char -> c == 'd'
cout << c; // prints 'd'
}
return 0;
}
The order in which the characters are stored in int is not specified by standard. However, a well designed compiler will consider endianness when storing a multi-character constant: GCC and VisualC behaves the same way.