1

I have this piece of C++ code:

const char *Delim = "some text";
char *token;
...
token = strtok('\0', Delim); // error here

The error is as follows:

invalid conversion from 'char' to 'char*' [-fpermissive]

I tested this in GCC 5.3 and it worked. But in GCC 8.1 it fails and gives me the error.

I understand I hard-code the char value. However, the Delim variable is also hard-coded. What would be the right replacement for it to work regardless of GCC versions? And why?

Note: I tested the following to get it to compile, but I want to understand it a bit more

const char *Delim = "some text";
char *str_0 = "\0"; // still receive warning that ISO C++ forbids converting a string constant to 'char*'
car *token;
...
token = strtok(str_0, Delim);

Interestingly, the single quote did not work either:

const char *Delim = "some text";
char *str_0 = '\0'; // fails
car *token;
...
token = strtok(str_0, Delim);
Cit5
  • 400
  • 5
  • 19
  • 1
    Does this answer your question? [Single quotes vs. double quotes in C or C++](https://stackoverflow.com/questions/3683602/single-quotes-vs-double-quotes-in-c-or-c) – JaMiT Aug 29 '20 at 03:26

1 Answers1

7

It's because the char expression '\0' is no longer a null pointer constant (and thus no longer convertible to a pointer), since C++11. Your newer compiler uses a new version of C++ by default.

You're supposed to pass an actual null pointer (i.e. nullptr, or NULL in the old days) to that argument, not '\0'. In the past your code only worked because of a weird kind of implicit conversion that eventually got removed. It's possible that this conversion masked a misunderstanding of what passing a null pointer there means (it means "continue the previous tokenisation session please", not "use '\0' as delimiter").

So:

token = strtok(nullptr, Delim);

I also recommend that you tell GCC exactly which version of C++ you're writing, with the -std flag.

char *str_0 = "\0"; // still receive warning that ISO C++ forbids converting a string constant to 'char*'

This has been advised against for a long time, and illegal for almost a decade. String literals should be stored in a const char*, not a char*. They're immutable (constant).

Regardless, this variant of the code does a different thing; you're now tokenising the string str_0, not continuing tokenising the original string.

Finally, I think you may have got the arguments backwards in your mind. Delim is supposed to be a list of delimiters, not an input string. It's hard to know for sure without a concrete example of your problem, but "some text" doesn't even look like a placeholder for a list of delimiters.

Please review some strtok documentation, or the section on it in your favourite book, to refresh your memory on how it's supposed to be used.

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35
  • 1
    Also see if, as an extension, your version of the C++ library has `strtok_s`. I donʼt know why the original `strtok` was defined in the way it was, but there are several problems with it, most notably that it can only save one set of state at once so if you want to tokenize multiple strings you need to be careful. – Daniel H Aug 29 '20 at 00:23