I have this code that works as expected:
#define MAX_PARAM_NAME_LEN 32
const char* GetName()
{
return "Test text";
}
int main()
{
char name[MAX_PARAM_NAME_LEN];
strcpy(name, GetName());
cout << "result: " << name << endl;
}
If I'd like to store the result to a char *
(because some functions within a Frameworks I'm using use only char *
as input) without using the strcpy
(for practicality and readability of code, and learning too), how could I do? Keeping in const
, this works well:
const char* name;
name = GetName();
but I still have const
.
Trying to just use char*
:
char* name;
name = GetName();
I get invalid conversion from 'const char*' to 'char*'
. What's the best habit for this kind of conversion?
char* const says that the pointer can point to a char and value of char pointed by this pointer can be changed. But we cannot change the value of pointer as it is now constant and it cannot point to another char.
You absolutely can assign const char* to std::string , it will get copied though. The other way around requires a call to std::string::c_str() .
The const char *Str tells the compiler that the DATA the pointer points too is const . This means, Str can be changed within Func, but *Str cannot. As a copy of the pointer is passed to Func, any changes made to Str are not seen by main....
The difference is that const char * is a pointer to a const char , while char * const is a constant pointer to a char . The first, the value being pointed to can't be changed but the pointer can be. The second, the value being pointed at can change but the pointer can't (similar to a reference).
The best habit for this kind of conversion is to use std::string
throughout your code. Since the framework that you are using takes const char*
as its input, you can always pass it the results of c_str()
call on your std::string
:
std::string GetName() {
return "Test text";
}
int main() {
std::string name = GetName();
int res = external_framework_function(name.c_str());
cout << "result: " << res << " for " << name << endl;
}
A distant second best is using const char*
in your code:
const char* name = GetName();
Since the framework that you are using takes const char*
you are good here as well.
If you need a non-const pointer, there is no way around copying the string. You can make a function that does it for you, but you would remain responsible for freeing the copies that you get from it:
char* copy(const char* orig) {
char *res = new char[strlen(orig)+1];
strcpy(res, orig);
return res;
}
...
char *name = copy(GetName());
...
delete[] name;
return "Test text";
returns a pointer to a read-only string literal.
If you're using a function that takes a char*
as an input, and you have a const char*
(such as a read-only string literal), then you ought to supply a deep copy of the string starting at that const char*
to such functions.
Else you risk undefined behaviour at runtime if a function attempts to modify a read-only string.
What you currently have is adequate; assuming you can't work with std::string
. (If you can work with std::string
and all your framework functions take a const char*
input, then I'd suggest your refactoring your code to use a std::string
, and pass the output of the c_str()
method on that string class to your framework functions.)
Finally, if some of your framework functions require a char*
then you could always build yourself a small adapter class:
class Adapter
{
public:
Adapter(const& Adapter) = delete; /*don't try to copy me please*/
Adapter& operator=(const Adapter& ) = delete; /*don't try to copy me please*/
Adapter(const char* s) : m_s(::strdup(s))
{
}
~Adapter() /*free memory on destruction*/
{
::free(m_s); /*use free to release strdup memory*/
}
operator char*() /*implicit cast to char* */
{
return m_s;
}
private:
char* m_s;
};
Then for a function void foo(char* c)
, you can call foo(Adapter("Hello"/*or any const char* */));
and foo
can do as it pleases with the char*
that's embedded in the anonymous temporary! You could even enhance this class to take a constructor to a char*
where in that case only a shallow copy of the pointer is taken (and the destructor doesn't delete the memory).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With