This question already has answers here:
returning a pointer to a literal (or constant) character array (string)?
(3 answers)
Closed 3 years ago.
I have a legacy code snippet that looks like:
const char *GetStr() const {
return ("");
}
I am wondering whether this is a risky code as instead of returning a global character pointer, returning a local string literal?
For example, perhaps, the following code snippet is better.
const char *NullStr = "";
const char *GetStr() const {
return NullStr; // instead of ""
}
What could be pros/cons?
Even the following implementation could be better:
const char *GetStr() const {
static const char * lNullStr = "";
return lNullStr;
}
Your first snippet is not strictly portable.
An alternative, which is, is:
const char *GetStr() const {
static const char* s = "";
return s;
}
and also has the benefit that s is contained within the function.
Related
In Stroustrup C++ 4thEd p176, he states that this code is safe because string literals are allocated statically
const char∗ f() { return "some literal"; }
I have two questions about that :
First, at which revision of C++ did that became the case? ( and is it implementation dependent ? )
Second, does this extend to any "const char*" ?
on this second part, I guess the answer is no, since this caused a run time error:
const char* make_const_char_ptr(){
const char res [] = {'a','b','c', '\0' };
return res;
}
First, at which revision of C++ did that became the case?
Always been the case since C++ was standardised. String literals have static storage duration.
Second, does this extend to any "const char*" ?
Yes, if you the the returned object has static storage. But that's not the case in your example. res has automatic storage duration. Instead you can do:
const char* make_const_char_ptr() {
static const char res [] = { 'a', 'b', 'c', '\0' };
return res;
}
and it's valid.
The statement refers to literals NOT to any const char*, you've got to mind the difference between a const char* and a literals.
The first line of code you mentioned:
const char∗ f() { return "some literal"; }
contains a literal "some literal" the compiler interpret that by statically allocating that string represented.
The other piece of code:
const char* make_const_char_ptr(){
const static char res [] = {'a','b','c', '\0' };
return res;
}
is interpreted as to allocate an array of char and then return the pointer to the begin of that array, but as soon the program returns from the function the array is being deallocated (so it is not safe to access any more to the address pointed by the returning value. Type of return is the same for both function but in first case is linked to a literal (statically allocated, not destroyed on return) in the other case you tell compiler to allocate an array which scope is confined to the function itself (contrary to the static case of the literal).
To return a reference or a pointer to a variable with the automatic storage duration from a function invokes undefined behavior because after exiting the function the referenced or pointed variable will not be alive.
String literals have static storage duration so you may return a pointer or a reference to a string literal.
Also you can return a reference or a pointer to a function local variable that is declared with the storage specifier static.
For example using this function definition
const char* make_const_char_ptr(){
const char res [] = {'a','b','c', '\0' };
return res;
}
this code snippet
const char *s = make_const_char_ptr();
size_t n = strlen( s );
invokes undefined behavior because the pointed string stored in the array res with the automatic storage duration will not be alive.
However if the function will be defined the following way
const char* make_const_char_ptr(){
const static char res [] = {'a','b','c', '\0' };
return res;
}
then this code snippet
const char *s = make_const_char_ptr();
size_t n = strlen( s );
is correct because the array res is still alive. The qualifier const does not matter in this case. That is it does not influence on the life time of the array.
Pay attention to that it is unimportant how the array is initialized: whether using a string literal or an initializer list of characters.
This declaration within the function
const char res [] = { "abc" };
has automatic storage duration if the storage specifier static is not present.
And below there is a demonstrative program where a string literal is returned from a function by reference.
#include <iostream>
#include <type_traits>
decltype( auto ) f()
{
return ( "hello World" );
}
void g( const char *s )
{
std::cout << s << '\n';
}
int main()
{
decltype( auto ) s = f();
g( s );
std::cout << std::extent<std::remove_reference<decltype( s )>::type>::value << '\n';
return 0;
}
The program output is
hello World
12
This question already has answers here:
Access violation writing location when working with pointers to char
(4 answers)
Closed 5 years ago.
I'm trying to implement tolower(char *) function, but I get access violation error. I came to know that this is because to compiler stores string literals in a read-only memory. Is this true?
Here's some code:
char* strToLower(char *str)
{
if(str == nullptr)
return nullptr;
size_t len = strlen(str);
if(len <= 0)
return nullptr;
for(size_t i = 0; i < len; i++)
*(str+i) = (char)tolower(*(str+i));//access violation error
return str;
}
int main()
{
char *str = "ThIs Is A StRiNgGGG";
cout << strToLower(str) << endl;
system("pause");
return 0;
}
If this is true, how am I supposed to implement such function?
Yes, it's true. You cannot modify a string literal. In fact, if your compiler were not from 1922 it would have prevented you from even obtaining a non-const pointer to a string literal in the first place.
You didn't state your goals, so when you ask "how am I supposed to implement such function" it's not really clear what you want to do. But you can make a copy of the string literal to get your own string, then modify that as you please:
// Initialises an array that belongs to you, by copying from a string literal
char str[] = "ThIs Is A StRiNgGGG";
// Obtains a pointer to a string literal; you may not modify the data it points to
const char* str = "ThIs Is A StRiNgGGG";
// Ancient syntax; not even legal any more, because it leads to bugs like yours
char* str = "ThIs Is A StRiNgGGG";
Of course, since this is C++, you should not be using C-strings in the first place:
std::string str("ThIs Is A StRiNgGGG");
This question already has answers here:
std::string to char*
(18 answers)
Closed 8 years ago.
I have a problem to output a string. Can you help me?
In the following, const char * i and const char ** o are given.
The statement, "*o = temp" produces an error, saying that "std::string" and "const char *" do not fit. What is the problem?
int mytask(const char * i, const char ** o)
{
std::string temp = std::string("mytask:") + i;
*o = temp; //How to modify?
return (0);
}
First of all you are trying to assign a local char pointer and use it in calling function, where it have already been destroyed. So instead you should do this. Assuming memory is allocated for o:
strcpy(*o,temp.c_str());
*o=temp means you are making the o point to a pointer that points to a std::string however o is a pointer that points to a char (or sequence of chars). This is not allowed. The other way around works: temp=*o because the std::string object defines what happens when you assign a char* to it (copy the null terminated string into the object). If you absolutely must copy from temp into the char* pointed to by o*. use strcpy() and std::string.c_str()
strcpy(*o,temp.c_str())
In C++, it's unusual to pass raw pointers around in this manner.
Returning 0 doesn't achieve much either.
I'd expect to see something like this:
std::string mytask(std::string const& i)
{
return "mytask:" + i;
}
int main()
{
std::string const number { '1' };
std::string const ret { mytask(number) };
}
The statement
strcpy(*o,temp.c_str());
didn't work. I resolved this problem by
*o = temp.c_srt();
instead. Thanks all anyway.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
I have the following function in c++
char* Test::convertToSHA(const char* cc) {
const char* salt ="sh$^$##!&7hbfvatfacv####bagg=shjgvshvcbschj";
time_t currentTime;
time(¤tTime);
CCString startTimeString;
startTimeString.createWithFormat("%d", currentTime);
std::string s = cc;
s += startTimeString.getCString();
s += salt;
char *str = new char[strlen(s.c_str()) + 1];
int length=strlen(str);
unsigned char hash[length*2];
char hexstring[41];
sha1::calc(str,length,hash);
sha1::toHexString(hash, hexstring);
return hexstring;
}
And in the call i use
char* output=NULL;
output= Test::convertToSHA("hello");
This is causing my code to crash. Is there a problem with me returning a string ? How can i return from this function ?
You can never return a local pointer in C or C++. Instead, either pass the pointer as a parameter:
void Test::convertToSHA(const char* cc, const char* hexstring) {
//no change to body
//no return statement needed
}
//then when calling the function:
char hexstring[41];
convertToSHA(cc, hexstring);
//hexstring has been modified
Or just use std::string instead. Use the c_str() if you need to convert to a c-style string (you still can't return the pointer, though).
I'm assuming you're using this library. I find it odd that it claims to be written in C++ but doesn't take advantage of C++ idioms. The function modifies the pointer, and doesn't return anything, so you do need a local variable. Lucky for you, std::strings will happily accept a char [] argument.
std::string Test::convertToSHA(const char* cc) {
// ...
char hexstring[41];
sha1::calc(str,length,hash);
sha1::toHexString(hash, hexstring);
std::string ret(hexstring);
return ret;
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert std::string to const char* or char*
void Foo::bar(const std::string& foobar) {
// ...
const char* foobar2 = (char*)foobar;
// ...
}
That does not work and I get an error during compilation about invalid casting.
Is there some other way to convert std::string to const char*?
Use foobar.c_str().
You might find this link useful: http://www.cppreference.com/wiki/string/start
std::string::c_str() gets you a const char* pointer to a character array that represents the string (null-terminated).
You should not manipulate the data this pointer points to, so if you need to do that, copy the data.
Double edit - doing it in a more C++ fashion
Since it is nicer to avoid the use of raw pointers and arrays where possible, you can also get the data into an std::vector<char>
#include <string>
#include <vector>
int main()
{
std::string str = "Hello";
std::vector<char> cvec(str.begin(), str.end());
// do stuff
}
edit this is more like C since it uses raw pointers and explicitly allocates mem
#include <string>
#include <cstring>
int main()
{
std::string str = "Hello";
char *cptr = new char[str.size()+1]; // +1 to account for \0 byte
std::strncpy(cptr, str.c_str(), str.size());
// do stuff...
delete [] cptr;
}
You're going to get a lot of kinda incorrect answers about str.c_str() here. :) While c_str() is indeed useful, please keep in mind that this will not actually convert the string into a char*, but rather return the contents of the string as a const char*. And this is a big difference!
What's important here is that the pointer you obtain from c_str() is valid only as long as the given string object exists. So this would be terribly wrong:
class Something {
const char* name;
public:
Something(const std::string& pname) {
this->name = pname.c_str(); /* wrong! the pointer will go wrong as the object from the parameter ceases to exist */
}
};
So if you want to convert, as in: create a new value which will be independent of the original std::string, then you'll want to do something like this:
char* convert(const std::string& str) {
char* result = new char[str.length()+1];
strcpy(result,str.c_str());
return result;
}
But still c_str() will be quite enough for you in most cases. Just try to think in terms of objects' time of life.
const char* foobar2 = foobar.c_str();
Notice the const.
Otherwise you have to copy it to a char buffer.