I need to convert number to string and store it into a const char* but problem is that const char* variable is blank after assignment.
In the following example code I expect to see number output converted to const char*
#include <iostream>
#include <string>
int main()
{
int number = 123;
const char* ptr_num_string = std::to_string(number).c_str();
std::cout << "number to string is: " << ptr_num_string << std::endl;
std::cin.get();
return 0;
}
Output is blank:
number to string is:
How do I convert number into a const char* ?
std::to_string returns a temporary std::string.
The pointer returned by std::string::c_str is invalidated by any non-const operation on the string itself - this is because it basically gives you a pointer to the string's internal buffer.
Destroying a std::string is definitely a non-const operation!
Therefore, you can't expect to take a pointer into the string returned by to_string and ever be able to use that. You need to save a copy of that string in the first place:
int number = 123;
std::string const numAsString = std::to_string(number);
char const* ptrToNumString = numAsString.c_str(); // use this as long as numAsString is alive
What you are doing is called Undefined Behaviour - this means that your program is invalid, and anything could happen. It could crash, it could print out some garbage, it could appear to work normally, it could do a different one of these each time you run your program...
It is not "blank" it points to the buffer of string that went out of scope. So accessing it causes Undefined Behavior. You need to keep string alive:
auto str{std::to_string(number)};
auto ptr_num_string{str.c_str()};
std::cout << "number to string is: " << ptr_num_string << std::endl;
Related
I'm having troubles initializing a global variable. My C++ is a bit rusty so I can't remember the reason why my code isn't working.
file.cpp
const char * write_path = &(std::string(getenv("FIFO_PATH")) + "/pythonread_fifo")[0];
int main(int argc, char**argv)
{
std::cout << "printing a string: ";
std::cout << (std::string(getenv("FIFO_PATH")) + "/pythonread_fifo\n");
std::cout << "printing a const char*: ";
std::cout << &(std::string(getenv("FIFO_PATH")) + "/pythonread_fifo")[0] << std::endl;
std::cout << "printing write_path:";
std::cout << write_path;
std::cout << write_path << std::endl;
std::cout << "printing FIFO_PATH:" << std::string(getenv("FIFO_PATH"));
}
As a premise: FIFO_PATH has been correctly added to bashrc, and it works, however, when I launch this program this is the output:
printing a string: /home/Processes/FIFOs/pythonread_fifo
printing a const char*: /home/Processes/FIFOs/pythonread_fifo
printing write_path:
printing FIFO_PATH:/home/Processes/FIFOs
As you can see write_path is completely empty.
What's even stranger to me is that if I define write_path as:
const char * write_path = "/home/Processes/FIFOs/pythonread_fifo";
Then write_path is no longer empty, it's correctly initialized and printed.
How can I solve this? Or at the very least, why is this happening?
EDIT: The issue IS NOT related to write_path being global. I placed the definition inside the main and when I try to print write_path, it's still empty
write_path is initialized as a pointer pointing to the 1st element of a temporary std::string, which will be destroyed immediately after the full expression, left write_path dangled, dereference on it leads to UB.
You can use std::string directly, or use a named std::string, then get the pointer from it.
std::string s = std::string(getenv("FIFO_PATH")) + "/pythonread_fifo";
const char * write_path = &s[0]; // or s.c_str()
On the other hand,
const char * write_path = "/home/mverrocc/dss_cp/dss-cp/Processes/FIFOs/pythonread_fifo";
works fine, the c-style string literal has static storage duration and exists in memory for the life of the program, then write_path is always a valid pointer.
const char * write_path = &(std::string(getenv("FIFO_PATH")) + "/pythonread_fifo")[0];
constructs a temporary std::string, takes the address of it's first character then discards the string, thus deleting the underlying char array. This is UB.
Better just use std::string and use c_str() when you need a const char*
You're creating a temporary std::string object, and get a pointer to its first character. This pointer will become invalid as soon as the expression &(std::string(getenv("FIFO_PATH")) + "/pythonread_fifo")[0] ends, when the temporary object is destructed.
Use a std::string object for write_path as well, define it inside the main function, and use the c_str function of the string when you need a null-terminated string.
I have a const char pointer which I know for sure came from a string. For example:
std::string myString = "Hello World!";
const char* myCstring = myString.c_str();
In my case I know myCstring came from a string, but I no longer have access to that string (I received the const char* from a function call, and I cannot modify the function's argument list).
Given that I know myCstring points to contents of an existing string, is there any way to safely access the pointer of the parent string from which it originated? For example, could I do something like this?
std::string* hackyStringPointer = myCstring - 6; //Along with whatever pointer casting stuff may be needed
My concern is that perhaps the string's contents possibly cannot be guaranteed to be stored in contiguous memory on some or all platforms, etc.
Given that I know myCstring points to contents of an existing string, is there any way to safely access the pointer of the parent string from which it originated?
No, there is no way to obtain a valid std::string* pointer from a const char* pointer to character data that belongs to a std::string.
I received the const char* from a function call, and I cannot modify the function's argument list
Your only option in this situation would be if you can pass a pointer to the std::string itself as the actual const char* pointer, but that will only work if whatever is calling your function does not interpret the const char* in any way (and certainly not as a null-terminated C string), eg:
void doSomething(void (*func)(const char*), const char *data)
{
...
func(data);
...
}
void myFunc(const char *myCstring)
{
std::string* hackyStringPointer = reinterpret_cast<std::string*>(myCstring);
...
}
...
std::string myString = "Hello World!";
doSomething(&myFunc, reinterpret_cast<char*>(&myString));
You cannot convert a const char* that you get from std::string::c_str() to a std::string*. The reason you can't do this is because c_str() returns a pointer to the string data, not the string object itself.
If you are trying to get std::string so you can use it's member functions then what you can do is wrap myCstring in a std::string_view. This is a non-copying wrapper that lets you treat a c-string like it is a std::string. To do that you would need something like
std::string_view sv{myCstring, std::strlen(myCstring)};
// use sv here like it was a std::string
Yes (it seems), although I agree that if I need to do this it's likely a sign that my code needs reworking in general. Nevertheless, the answer seems to be that the string pointer resides 4 words before the const char* which c_str() returns, and I did recover a string* from a const char* belonging to a string.
#include <string>
#include <iostream>
std::string myString = "Hello World!";
const char* myCstring = myString.c_str();
unsigned int strPtrSize = sizeof(std::string*);
unsigned int cStrPtrSize = sizeof(const char*);
long strAddress = reinterpret_cast<std::size_t>(&myString);
long cStrAddress = reinterpret_cast<std::size_t>(myCstring);
long addressDifference = strAddress - cStrAddress;
long estStrAddress = cStrAddress + addressDifference;
std::string* hackyStringPointer = reinterpret_cast<std::string*>(estStrAddress);
cout << "Size of String* " << strPtrSize << ", Size of const char*: " << cStrPtrSize << "\n";
cout << "String Address: " << strAddress << ", C String Address: " << cStrAddress << "\n";
cout << "Address Difference: " << addressDifference << "\n";
cout << "Estimated String Address " << estStrAddress << "\n";
cout << "Hacky String: " << *hackyStringPointer << "\n";
//If any of these asserts trigger on any platform, I may need to re-evaluate my answer
assert(addressDifference == -4);
assert(strPtrSize == cStrPtrSize);
assert(hackyStringPointer == &myString);
The output of this is as follows:
Size of String* 4, Size of const char*: 4
String Address: 15725656, C String Address: 15725660
Address Difference: -4
Estimated String Address: 15725656
Hacky String: Hello World!
It seems to work so far. If someone can show that the address difference between a string and its c_str() can change over time on the same platform, or if all members of a string are not guaranteed to reside in contiguous memory, I'll change my answer to "No."
This reference says
The pointer returned may be invalidated by further calls to other member functions that modify the object.
You say you got the char* from a function call, this means you do not know what happens to the string in the mean time, is that right? If you know that the original string is not changed or deleted (e.g. gets out of scope and thus is destructed) then you can still use the char*.
Your example code however has multiple problems. You want to do this:
std::string* hackyStringPointer = myCstring - 6;
but I think you meant
char* hackyStringPointer = myCstring;
One, you cannot cast the char* to a string* and second you do not want to go BEFORE the start of the char*. The char* points to the first character of the string, you can use it to access the characters up to the trailing 0 character. But you should not go before the first or after the trailing 0 character though, as you do not know what is in that memory or if it even exists.
This question already has answers here:
What is the lifetime of the result of std::string::c_str()?
(7 answers)
Closed 5 years ago.
Consider the MWE below,
std::string return_string()
{
return "this is a string"
}
int main()
{
const char *y = return_string().c_str();
std::string str = return_string();
const char *x = str.c_str();
std::cout << return_string() << std::endl; //Prints "this is a string"
std::cout << y << std::endl; // Prints Weird characters
std::cout << x << std::endl; //Prints "this is a string"
std::cin.ignore();
return 0;
}
I have a function which returns a string and I need to convert it to a c-style string. Doing return_string().c_str() gives me weird output like
▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌p. But if I store the output of a function in a string first and then convert that string to a c-style string it works. What is wrong with the first way?
When you do return_string().c_str() you get the pointer to a temporary object that will go out of scope once the expression is finished. If you save the pointer and use it later you will have undefined behavior.
With
std::string str = return_string();
you copy the returned temporary object. Getting a pointer to the copy will work since it still exists in the program at the point when you use the pointer.
const char *y = return_string().c_str();
is a problem if you wish to use y later to access the contents. In that line, the return value of return_string() is a temporary that gets destroyed after that line is executed. Hence, y is dangling pointer.
Accessing the contents of a dangling pointer causes undefined behavior.
When you use
std::string str = return_string();
const char *x = str.c_str();
x is not a dangling pointer as long as str is in scope. Hence,
std::cout << x << std::endl;
is well behaved.
You can't "convert from string to const char*". No such thing exists, because a const char* does not contain characters. It is not a string! It only pointers to some characters somewhere.
In this case, via std::string::c_str(), it points to characters that no longer exist.
I have a very simple code snippet:
#include <iostream>
using namespace std;
string getString() {
return "test";
}
int main(){
const char* testString = getString().c_str();
cout << "string 1:" << testString << endl;
string dummy[] = {"1","2","0"};
cout << "string 2:" << testString << endl;
return 0;
}
I expect the two couts will print the same output, but the output I got is
string 1:test
string 2:1
Can anyone explain why is this happening? Also, there are two things that I observed:
1) If dummy[] is of int type, then they will print the exact same strings test as expected.
2) If I first assign getString() to a string variable, then change the first line in main to const char* testString = variable.c_str(); then they will cout the same strings as expected.
The behavior is undefined.
const char* testString = getString().c_str();
getString returns a temporary object which is destroyed when the evaluation completes. As the result. testString points at internals of a destroyed object, causing undefined behavior.
In practice, it may happen that the data is still at that address for some time, that's why the first cout gives illusion of correctness.
You set pointer to a temporary object that will be deleted after this declaration
const char* testString = getString().c_str();
So the program has undefined behaviour.
The correct code could look like
const char * getString() {
return "test";
}
int main(){
const char* testString = getString();
//...
because string literals have static storage duration.
When you get a low level character pointer from a string object that manages the memory for that string, the pointer is only good for as long as that specific object is alive.
It's more narrow than that, actually. If you call any non-const members on the string object, it means you can't trust any values you got from previous calls to c_str() to still be good--even if the object destructor has not run.
#include <iostream>
using namespace std;
string getString() {
return "test";
}
int main(){
string testString = getString();
const char * testCstring = testString.c_str();
cout << "string 1:" << testCstring << endl;
string dummy[] = {"1","2","0"};
cout << "string 2:" << testCString << endl;
return 0;
}
That's legal, but do not rely upon the pointer from c_str() after you have made any modifying change to the string you got it from -or- that string having been destroyed.
Also note there's no need to get a char * from a string in order to output it. Start thinking in terms of using string objects and don't go to char * unless you have a good reason.
I'm a C/C++ beginner trying to build what seems like a pretty simple program: it loads a file into a c-string (const char*). However, although the program is incredibly simple, it's not working in a way I understand. Take a look:
#include <iostream>
#include <fstream>
std::string loadStringFromFile(const char* file)
{
std::ifstream shader_file(file, std::ifstream::in);
std::string str((std::istreambuf_iterator<char>(shader_file)), std::istreambuf_iterator<char>());
return str;
}
const char* loadCStringFromFile(const char* file)
{
std::ifstream shader_file(file, std::ifstream::in);
std::string str((std::istreambuf_iterator<char>(shader_file)), std::istreambuf_iterator<char>());
return str.c_str();
}
int main()
{
std::string hello = loadStringFromFile("hello.txt");
std::cout << "hello: " << hello.c_str() << std::endl;
const char* hello2 = loadCStringFromFile("hello.txt");
std::cout << "hello2: " << hello2 << std::endl;
hello2 = hello.c_str();
std::cout << "hello2 = hello.c_str(), hello2: " << hello2 << std::endl;
return 0;
}
The output looks like this:
hello: Heeeeyyyyyy
hello2: 青!
hello2 = hello, hello2: Heeeeyyyyyy
The initial hello2 value changes every time, always some random kanji (I'm using a Japanese computer, so I'm guessing that's why it's kanji).
In my naive view, it seems like the two values should print identically. One function returns a c++ string, which I then convert to a c-string, and the other loads the string, converts the c-string from that and returns it. I made sure that the string was loading properly in loadCStringFromFile by couting the value before I returned it, and indeed it was what I had thought, e.g.:
/*(inside loadCStringFromFile)*/
const char* result = str.c_str();
std::cout << result << std::endl;//prints out "Heeeyyyyyy" as expected
return result;
So why should the value change? Thanks for the help...
Your problem is that str in loadCStringFromFile is a local variable, and is destructed when the function returns. At that point the return value from c_str() is invalid.
More detail here
Your first function, loadStringFromFile, is a more C++-like way of doing it, and illustrates the benefit of having a class manage memory for you. If you use char* then you have to take much more care where memory is allocated and freed.
the function
std::string loadStringFromFile(const char* file)
returns a string copy of the string created inside the function which is copied before the string goes out of scope i.e. the function ends, that is why it works.
const char* loadCStringFromFile(const char* file)
on the other hand returns a pointer to the local string which goes out of scope when the function returns and is destroyed so the returned address, the const char*, points to somewhere undefined.
in order for the second way to work you either need to create the string before calling the function :
const char* loadCStringFromFile(const char* file, string& str); // return str.c_str()
..
string str;
const char* result = loadCStringFromFile(file,str);
or you create a string on the heap in the function and pass the address back, but that gets a bit messy since the caller would need to delete the string to avoid memleak.
You should duplicate output of str.c_str():
return strdup(str.c_str);
function strdup can be found in cstring header.