Learn

Fixing "cannot convert 'String' to 'const char*'" in Arduino

Beginner

Or see every lesson.

  • 505parts on the bench
  • 45boards running now
  • 1.00xreal time, on every board
Arduino Uno: an I2C LCD that says hellolive0.000 s 0.00x
Click to open it in the editor
It scans the I2C bus, then writes Hello, inventor! on the LCD. In setup(), put String greeting = "Hello, inventor!"; and const char *text = greeting; above lcd.print, then Run: no viable conversion.

cannot convert 'String' to 'const char*' means the sketch gives a String object to something that wants C text, a const char *: a variable of that type, or a function such as strcmp, atoi or strcpy. A String is a class that holds its text inside it, and C++ does not turn one into a plain pointer on its own. The fix is nearly always .c_str(), which gives the String’s text as a const char *: strcmp(command.c_str(), "on").

GCC, which the Arduino IDE uses, adds where it happened: in initialization, in assignment or in return. Mokxi compiles with clang, which words it no viable conversion from 'String' to 'const char *'. The circuit above is a 16x2 I2C LCD on an Uno that writes "Hello, inventor!". Below is each way the error turns up, with clang’s words and GCC’s, and the fix for each.

"in initialization": a const char * made from a String

Change the LCD sketch to keep its greeting in a String, then hand it to a const char *, and the build stops at that line. Clang said no viable conversion from 'String' to 'const char *', and Mokxi’s build tab explains: "A String cannot become a const char * here. From a String: .toInt() or .toFloat() for a number, .c_str() for a const char *, .toCharArray() into a char array. To a String: String(value)." GCC 13 says cannot convert 'String' to 'const char*' in initialization for the same line.

There are two fixes. const char *text = greeting.c_str(); builds. Here it is simpler still to drop the pointer: lcd.print(greeting); takes a String as it is, and so do Serial.print and Serial.println. The same error comes from a global, const char *network = ssid; under String ssid = "Home";, which is how it often turns up in Wi-Fi sketches.

Broken: a String handed to a const char *
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.init();
  lcd.backlight();
  String greeting = "Hello, inventor!";
  const char *text = greeting;
  lcd.print(text);
}

void loop() {
}

Open this sketch in the editorThe code alone: the editor places the board and the parts it can read from the sketch.

"in assignment", and char * without the const

The same thing in two steps, const char *text; and later text = name;, gives GCC’s cannot convert 'String' to 'const char*' in assignment. Clang words this one assigning to 'const char *' from incompatible type 'String', and the build tab says "A String cannot be put in a char pointer. Put .c_str() after the String's name: text = name.c_str();."

Without the const, char *text = name; gave clang’s no viable conversion from 'String' to 'char *' and GCC’s cannot convert 'String' to 'char*' in initialization. .c_str() does not fix this one, because its text is read-only. If you need text you can change, copy it into a char array: name.toCharArray(buf, sizeof(buf));. That sketch printed "Mokxi".

In a call: strcmp, atoi, strcpy and your own functions

Most of the time the String goes into a function that takes C text. Reading a command from the serial port with Serial.readStringUntil('\n') gives a String, and passing it to strcmp fails. GCC 13 says cannot convert 'String' to 'const char*', with a note, initializing argument 1 of 'int strcmp(const char*, const char*)'. Older GCC, in many forum posts, put both in one line: cannot convert 'String' to 'const char*' for argument '1' to 'int strcmp(const char*, const char*)'.

Clang says no matching function for call to 'strcmp', with the note candidate function not viable: no known conversion from 'String' to 'const char *' for 1st argument, and Mokxi’s build tab says: "strcmp takes C text (a char array or a "quoted" string), not a String, as its 1st value. Put .c_str() after the String's name where you pass it, as in name.c_str(), which gives its text as C text." atoi(s), strcpy(buf, name) and a function of your own that takes const char * fail the same way.

For a String there is often a simpler way than the C function. command == "on" compares a String with text directly, and printed "on". s.toInt() reads a number, and "42" plus one printed 43, the same as atoi(s.c_str()) + 1.

Each one fixed with .c_str(), or with String’s own way
void setup() {
  Serial.begin(9600);
  String name = "Mokxi";
  const char *text = name.c_str();
  Serial.println(text);
  String cmd = "on";
  if (strcmp(cmd.c_str(), "on") == 0) {
    Serial.println("matched");
  }
  String s = "42";
  Serial.println(atoi(s.c_str()) + 1);
  Serial.println(s.toInt() + 1);
}

void loop() {
}

Open this sketch in the editorThe code alone: the editor places the board and the parts it can read from the sketch.

"in return": a function that returns a String as const char *

A function declared const char *label() that builds a String and returns it gives GCC’s cannot convert 'String' to 'const char*' in return, and clang’s no viable conversion from returned value of type 'String' to function return type 'const char *'.

Do not fix this one with return text.c_str();. That builds, but the String is a local variable and is destroyed when the function returns, so the pointer points at memory that has been given back. Return the String itself instead: change the function to String label().

sprintf with a String: an error here, a warning in GCC

sprintf(buf, "%s", name) with a String is the same mistake in a place where the compiler cannot convert anything, because sprintf takes any number of values of any type. Clang stops: cannot pass non-trivial object of type 'String' to variadic function; expected type from format string was 'char *', and the build tab says "sprintf, snprintf and printf take C strings, not a String. Pass the String as name.c_str() instead."

GCC 13 only warns, format '%s' expects argument of type 'char*', but argument 3 has type 'String', and the Arduino IDE hides warnings unless you turn them on in its preferences, so the sketch builds and prints nonsense. Pass name.c_str().

Open this circuit in the editor. Arduino Uno: an I2C LCD that says hello, wired as it runs at the top of this page. Change a part or a value and run it again.

Open the circuit

Questions

How do I convert a String to const char* in Arduino?

Call .c_str() on it: const char *text = name.c_str();. The pointer is good while the String exists and is not changed, so use it right away rather than keeping it.

What does "cannot convert 'String' to 'const char*' in initialization" mean?

A const char * variable was given a String as its starting value. Add .c_str() after the String, or keep the String and pass it to print as it is.

Why does strcmp give this error?

strcmp takes C text, not a String. Write strcmp(command.c_str(), "on"), or compare the String directly with command == "on".

Does Mokxi show the same error?

Mokxi compiles with clang, which says no viable conversion from 'String' to 'const char *', or no matching function for call to 'strcmp' in a call. Its build tab tells you to use .c_str().

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.