In C++ 11, how can we initialize a char* with an empty string?

Pages: 12
I tried this:

 
char* buffer = static_cast<char*>( "");


Gives error:

error C2440: 'static_cast': cannot convert from 'const char [1]' to 'char *'



I also tried:

 
char* buffer = ""s.c_str();


Was not accepted either...


?

Regards,
Juan Dent
Last edited on
char * buffer { nullptr }; ?
what I meant by a empty string was something like "" (containing a null character not being a nullptr)

in other words something I can apply strlen() to and get 0.

Perhaps I don’t understand your question.
A char* is just a pointer; as every pointer, you need a (owned) memory area to initialize it to.
If you want to inizialise it to a string literal, since string literals are stored in read-only memory, you need to declare it const.

Otherwise you can sacrifice a few bit like so:
1
2
3
4
5
6
7
8
9
10
#include <cstring>
#include <iostream>


int main()
{
    char c { '\0' };
    char * buffer { &c };
    std::cout << std::strlen(buffer) << '\n';
}


Output:
0

this works for me:

char* TAG = "";
char* buffer;
*buffer = ''; // or

char s='', *buffer;
buffer = &s;
Last edited on
@abdulbadii
1
2
char* buffer;
*buffer = ''; // Undefined behavior -> most likely a crash. The pointer is invalid 


Juan Dent wrote:
Was not accepted either...
As @Enoizat told you, you're trying to assign a pointer to a const value to a pointer to a non const value. What are you trying to achieve?
Last edited on
mzimmers wrote:
this works for me:

char* TAG = "";
1
2
3
4
5
6
7
8
9
#include <cstring>
#include <iostream>


int main()
{
    char* TAG = "";
    std::cout << std::strlen(TAG) << '\n';
}


Output:
g++ -std=c++2a main.cpp -o main.exe
main.cpp: In function 'int main()':
main.cpp:7:17: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    7 |     char* TAG = "";
      |                 ^~


- - -

abdulbadii wrote:
char* buffer;
*buffer = ''; // or

char s='', *buffer;
buffer = &s;
1
2
3
4
5
6
7
8
9
10
11
#include <cstring>
#include <iostream>


int main()
{
    char* buffer;
    *buffer = '';

    std::cout << std::strlen(buffer) << '\n';
}

g++ -std=c++2a main.cpp -o main.exe
main.cpp:8:15: error: empty character constant
    8 |     *buffer = '';
      |               ^~


- - -
@JUANDENT, my code was just an example: let me point out that, since ‘c’ is a local variable, if you returned ‘buffer’ from a function, it would point to a non-owned memory area.
Here’s a different example:
1
2
3
4
5
6
7
8
9
10
#include <cstring>
#include <iostream>


int main()
{
    char * buffer { new char { '\0' } };
    std::cout << std::strlen(buffer) << '\n';
    delete buffer;
}

But, seriously, why do you mess with C-style char*? What’s bad in std::strings?
dunno about the OP but I have to deal with a number of 'C interfaced' tools that send and expect back a C-string. If the code is doing anything interesting or can make use of string/algorithm tools, I will convert it to and from and use what I needed. But if all it is doing is something really simple, I may not bother.

char cs[maxsize] = {0}; //KISS version.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <cstring>

int main()
{
   char* buffer { new char { } };

   std::cout << std::strlen(buffer) << "\n\n";

   std::cout << sizeof(*buffer) << "\n\n";

   std::cout << std::boolalpha << (buffer[0] == '\0') << '\n';
}
0

1

true

An empty C-string doesn't mean there are no characters in the string, there has to be the terminating '\0' character.

Creating a C-string like this -- a pointer to a char -- is rather messy, requiring a lot of (IMO) unnecessary memory management during its lifetime. std::string does all the memory management for you.
how about using an IILE?
char* p = []{ static char a[] = ""; return a; }();
Sorry, @Cubbi, but won’t (the memory pointed by) ‘p’ live forever in your example? I mean, there’s no way to delete it, is there?
won’t (the memory pointed by) ‘p’ live forever in your example?

yes, same as with const char* p = ""; which I assume the OP wanted to imitate most closely (based on "static_cast<char*>( "");")
That's the most convoluted way I've ever seen to declare a character ;)

I have a feeling we're not seeing the full picture of what's happening.

Also, because I don't think anyone else said it:
char* buffer = ""s.c_str();
Even if this were valid, you would be getting a pointer to a temporary object. ""s is no longer an object after that statement finishes.
Last edited on
char * b = &s[0]; //s is string. this works, but its not useful. s may not have a zero where you want it for c-string, because string works off the length not a terminal. if you modify b's data, and change the length, you will have bad problems. this may be what you wanted to express, but don't do this.

you really only need 3 things in practice for most anything you probably want to do here.
char array, and use the array name as a pointer as needed (to pass to functions etc)
char *, to accept the result of strstr or as a location inside your char array for any magic you are working, and
a string object if you want to convert to and from (inefficient if careless). Those items with string algorithms and C-string functions can do 100% of anything normal without any fuss.

no dynamic memory should be needed for a few small strings. Nothing weird or complicated. I know you guys are having fun, but if he needs to actually use a c-string for something ... there is no reason to over-engineer it.



Last edited on
@Cubbi, thank you for your answer.
@Cubbi what is an IILE? My guess is Inline Initialized Literal Expression...

C++ 17 does not allow:

 
char* TAG = "";


Why is this true:

 
char* buffer = ""s.c_str();



you would be getting a pointer to a temporary object. ""s is no longer an object after that statement finishes


why does calling c_str() on a string destroys the string?
it does not!
it is a temporary string variable in that specific statement, not the c_str() call that is a problem.
it creates a temp string, gets the pointer, and then destroys the temp object, leaving you hanging.

if you said this:
string s = "blah";
char* b = s.c_str(); // may need to watch out for const here
cout << s; //fine, s is untouched.
cout << b; //fine, b is still valid.

do you see it? there is no 'variable' of type string in the questioned example: look at it, what is the string variable's name?

one more time, its like doing this:
char *b;
{
string s = "word";
b = s.c_str();
} //s is destroyed, its scope-block ends here
b is invalid here... same as the first example, but explicitly showing the hidden variable.
Last edited on
Temporary objects created in an expression live until the semicolon (what's technically called the full expression.)

IILE: Immediately Invoked Lambda Expression.
Last edited on
Pages: 12