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

Pages: 12
Oct 21, 2019 at 9:50pm
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 Oct 21, 2019 at 9:50pm
Oct 21, 2019 at 10:06pm
char * buffer { nullptr }; ?
Oct 21, 2019 at 10:23pm
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.

Oct 21, 2019 at 10:44pm
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

Oct 21, 2019 at 10:54pm
this works for me:

char* TAG = "";
Oct 22, 2019 at 3:31am
char* buffer;
*buffer = ''; // or

char s='', *buffer;
buffer = &s;
Last edited on Oct 22, 2019 at 6:58am
Oct 22, 2019 at 8:17am
@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 Oct 22, 2019 at 8:21am
Oct 22, 2019 at 8:31am
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?
Oct 22, 2019 at 2:36pm
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 Oct 22, 2019 at 2:37pm
Oct 22, 2019 at 3:00pm
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.
Oct 22, 2019 at 4:31pm
how about using an IILE?
char* p = []{ static char a[] = ""; return a; }();
Oct 22, 2019 at 6:20pm
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?
Oct 22, 2019 at 6:41pm
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*>( "");")
Oct 22, 2019 at 8:04pm
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 Oct 22, 2019 at 8:14pm
Oct 22, 2019 at 8:41pm
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 Oct 22, 2019 at 8:42pm
Oct 22, 2019 at 9:34pm
@Cubbi, thank you for your answer.
Oct 23, 2019 at 7:40pm
@Cubbi what is an IILE? My guess is Inline Initialized Literal Expression...

C++ 17 does not allow:

 
char* TAG = "";


Oct 23, 2019 at 7:44pm
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?
Oct 23, 2019 at 7:47pm
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 Oct 23, 2019 at 7:52pm
Oct 23, 2019 at 10:51pm
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 Oct 23, 2019 at 10:53pm
Pages: 12