Search code examples
c++stringcasting

Assigning string literal to char*: const_cast<char *> vs using char array


I'm using some C functions in my C++ environment. And I get the following warnings because C++ doesn't allow assigning string literal to char * type.

C++11 does not allow conversion from string literal to char *

My Code:

void sys_vgui(char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    //do something
    va_end(ap);
}

void open(t_buf *x)
{ 
    sys_vgui("wm deiconify .x%lx\n", x);
    sys_vgui("raise .x%lx\n", x);
    sys_vgui("focus .x%lx.text\n", x);
}

And I could remove these warnings by const casting the string literals as the following.

sys_vgui(const_cast<char *>("wm deiconify .x%lx\n"), x);
sys_vgui(const_cast<char *>("raise .x%lx\n"), x);
sys_vgui(const_cast<char *>("focus .x%lx.text\n"), x);

But I'm not sure if it's really safe as I've seen many people saying not to directly cast string literal to char *.

So I came up with the following which seems like a safer solution.

char str1[] = "wm deiconify .x%lx\n";
sys_vgui(str1, x);
char str2[] = "raise .x%lx\n";
sys_vgui(str2, x);
char str3[] = "focus .x%lx.text\n";
sys_vgui(str3, x);

But it makes my code dirty and harder to maintain as I have to create multiple variables using different names(e.g. str1, str2, str3...) whenever I use the function.

So my questions are:

1) Is it really not safe to use const_cast<char *> in my case?

2) Any solution to write a clean code using char arrays without having to create multiple variables using different names?


Solution

  • It is safe as long as sys_vgui does not modify the string, which presumably it doesn't because modifying a string literal has undefined behavior in C, const or not. So if you have something like

    sys_vgui("wm deiconify .x%lx\n", x);
    

    in C, then the C++ version with const_cast is just as safe.

    However, to de-uglify the C++ code, I'd probably write a wrapper function:

    template<typename ...Ts>
    void xsys_vgui(const char *fmt, Ts ...args) {
        sys_vgui(const_cast<char *>(fmt), args ...);
    }
    

    Now

    xsys_vgui("wm deiconify .x%lx\n", x);
    

    should "just work" in C++.