what is the problem in arduino
C:\Users\swartwq\Desktop\zx\sketch_jun06e\sketch_jun06e.ino:12:33: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
In C++
char* a = "a"; //invalid
const char* b = "b"; // valid
char c[] = "c"; //valid
The reason why the first line is invalid is that a is a pointer to static read-only data and therefore is wrong to be non-const. C on the other hand is ok because the string "c" is allocated immediately on the stack and can therefore be changed.
Related
As per the output of this code snippet, the type of &"hello" is const char(*)[6], so char* ptr = &"hello"; is inlegal for char* and const char(*)[6] are different types.
And since char* ptr1 = "hello"; compiles with C++11 and latter, the type of "hello" is char*?
If the type of "hello" is char*, then &"hello" shouldn't be a pointer which points to char*(i.e. char**)?
I used to write char* ptr1 = "hello"; many years, and when I know that "hello" is a prvalue. A question raises that I could acquire the address of the string literal.After I found the type of &"hello" is const char(*)[6], I am totally confued now.
Could anybody shed some light on this matter?
Here is the aforementioned code snippet:
#include<memory>
#include<thread>
#include<iostream>
#include<typeinfo>
int main()
{
char* ptr = &"hello";
char* ptr1 = "hello";
}
Here is what the compiler complains:
<source>: In function 'int main()':
<source>:8:17: error: cannot convert 'const char (*)[6]' to 'char*' in initialization
8 | char* ptr = &"hello";
| ^~~~~~~~
| |
| const char (*)[6]
<source>:9:18: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
9 | char* ptr1 = "hello";
| ^~~~~~~
UPDATE:
Thanks to ShadowRanger's clarification. I realise that type of string literal is const char[6].
"Hello" is a string literal of type const char [6] which decays to const char* due to type decay.
Now let's see what is happening for each of the statements in you program.
Case 1
Here we consider the statement:
char* ptr = &"hello";
As i said, "hello" is of type const char [6]. So, applying the address of operator & on it gives us a const char (*)[6] which is read as a pointer to an array of size 6 with elements of type const char.
This means that there is a mismatch in the type on the right hand side(which is const char (*)[6]) and the left hand side(which is char*). And since there is no implicit conversion from a const char (*)[6] to a char* the compiler gives the mentioned error saying:
cannot convert 'const char (*)[6]' to 'char*'
Case 2
Here we consider the statement:
char* ptr1 = "hello"; //invalid C++
Since "Hello" is of type const char[6] meaning that the char elements inside the array are immutable(or non-changable). As i said, the type const char[6] decays to const char*. Thus on the right hand side we have a const char*. So if we were allowed to write char* ptr1 = "Hello"; then that would mean that we're allowed to change the elements of the array since there is no low-level const on ptr1. Thus, allowing char* ptr1 = "Hello"; would allow changing const marked data, which should not happen(since the data was not supposed to change as it was marked const). This is why the mentioned warning said:
ISO C++ forbids converting a string constant to 'char*'
So to prevent this from happening we have to add a low-level const as shown below:
vvvvv---------------------------> note the low-level const
const char* ptr1 = "Hello"; //valid c++
so that the pointer ptr1 is not allowed to change the const marked data.
By adding the low-level const highlighted above, it is meant that we're not allowed to change the underlying characters of the array.
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.
I am working on a Qt5 project written in C++. Building the project gives an error:
C2440: '=': cannot convert from 'const char [9]' to 'char*'
Which points to the line of code below:
port_name= "\\\\.\\COM4";//COM4-macine, COM4-11 Office
SerialPort arduino(port_name);
if (arduino.isConnected())
qDebug()<< "ardunio connection established" << endl;
else
qDebug()<< "ERROR in ardunio connection, check port name";
//the following codes are omitted ....
What is the problem here, and how can I correct it?
In C++, in contrast to C, string literals are const. So any pointer to such a string literal must be const, too:
const char* port_name = "\\\\.\\COM4"; // OK
// char* port_name = "\\\\.\\COM4"; // Not OK
String literals are constant data in C++ (compilers tend to store them in read-only memory when possible).
In C++11 and later, you can no longer assign a string literal directly to a pointer-to-non-const-char (char*) 1.
1: though some C++11 compilers may allow it as a non-standard extension for backwards compatibility, which may need to be enabled manually via compiler flag.
So, you need to declare port_name as a pointer-to-const-char instead (const char * or char const *). But then you will have to cast it back to a non-const char* when passing it to SerialPort():
const char *port_name = "\\\\.\\COM4";
SerialPort arduino(const_cast<char*>(port_name));
Or simply:
SerialPort arduino(const_cast<char*>("\\\\.\\COM4"));
The alternative is to declare port_name as a non-const char[] buffer, copy the string literal into it, and then pass it to SerialPort():
char port_name[] = "\\\\.\\COM4";
SerialPort arduino(port_name);
String declaration works when I declare in the the following ways:
string a = "xyz";
char a[] = "xyz";
But in case of:
char *a = "xyz";
It gives an ERROR in g++ 4.9.2 compiler:
warning: deprecated conversion from string constant to ‘char*’
[-Wwrite-strings] char *a = "xyz";
I think these three declaration types are different from each other. Please help me out.
string a = "xyz";
This uses initializer syntax to invoke the constructor std::string( const char* ).
char a[] = "xyz";
This declares an array large enough to store the string plus terminator. It follows standard array-initializer rules. Think of it as equivalent to char a[] = { 'x', 'y', 'z', '\0' };
char *a = "xyz";
This takes a string literal ("xyz") and assigns it to a non-constant pointer. Within the language, such a pointer means it is okay to modify the string it points to, but that is undefined behaviour in this case, because string literals may not be modified. To prevent you from making such a mistake, the compiler gives you a warning. The following is valid and will not emit a warning:
const char *a = "xyz";
In earlier version(s) of the language, you could use:
char* a = "xyz";
Now, you must use:
char const* a = "xyz";
A string literal, such as "xyz" resides in the rea-only parts of the program. It can be used to initialize a char const* since you are not supposed to modify the contents of what a char const* points to. Using it to initialize a char* opens the possibility of a user modifying them accidentally. In addition, modifying such strings is cause for undefined behavior.
A string literal can also be used to initialize a char[]. In that case, the string literal is copied to the space allocated for the array. Hence, there is no risk of modifying read-only data of the program. Hence, using
char a[] = "xyz";
is OK.
The line
string a = "xyz";
invokes the constructor of string that takes a char const* and then uses that object to initialize a. Hence, that line is also OK.
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 have declared the string array in my code as follows.
char *arr[] ={
"xyz",
"abc",
"pqr",
NULL
};
When compile then got following warning
warning: deprecated conversion from string constant to 'char*''
i know that "xyz" and other string literal are const char and my array is char* so have resolve it by declaring my array const char* arr but i loss the control to point this array in another pointer.
So to resolve above issue have declared array as follows
char *arr[] ={
(char *)"xyz",
(char *)"abc",
(char *)"pqr",
NULL
};
But this type of declaration not fair when need large array (more then 100 string array).
So any one have idea to resolve it by another way.
You don't lose any re-pointing options by making the array a const char* arr[]. Note that there's a huge difference between const char * p (a mutable pointer to an immutable char) and a char * const p (an immutable pointer to a mutable char). This code is perfectly valid:
const char *arr[] = {
"xyz",
"abc",
"pqr",
NULL
};
arr[1] = "ghi";
Live example
There is a difference between a const char* and char *const if your pointer is a const char* you can still point it to another location but you cannot modify the elements it contains. The correct solution in this case is to make the array const char*.
String literals are constant, so you need const pointers to refer to them:
const char *arr[] = {
// whatever
};
Historically, it used to be possible (but dangerous) to convert string literals to non-const char*, for compatibility with ancient code that didn't know about const. This conversion has been deprecated for many years, and finally removed from the language in 2011.