How to convert const char* to char* in C?
Asked Answered
H

7

93

In my project there is a method which only returns a const char*, whereas I need a char* string, as the API doesn't accept const char*.

Any idea how to convert between const char* to char*?

Hurlee answered 28/8, 2014 at 13:6 Comment(7)
Beware that the API might have been design this way with good reasons in mind.Intact
@Intact I'd said this below and this is the situation: The const char* is returned by an objective-C string method[NSString's to be more specific). This is a path of a file which got saved. Now there is another C library's api which will be parsing this file and it only takes char* strings as arguments. Even if i pass the const char* string, the parsing happens but i get a warning which i don't want to see.Hurlee
As others pointed out: As you never know what the parser does (think of what strtok() does) make a copy of the data returned and pass on the copy. strdup()and free() are your friends.Intact
Can you tell us which functions they are and link to their documentation?Carbamate
Good to read, we could convince you to not simply cast away a meaningful warning. However don't forget to free() what strdup() allocated!Intact
And in C++ there is const_cast<>()Mobile
@Intact sure... Right now I'm dealing with an API which has "those reasons" and they're "we didn't care if anyone 50+ years later will be using our code". Which is literally the only good reason I can think of, care to elaborate on what exactly what do you mean? For reference, I'm looking at this function int execvp(const char *file, char *const argv[]); and considering I'm using modern C++, my reason for abstracting it is "fuck your arcane bullshit reasons". Except it doesn't work as well as I expected it to, thanks to the fact that argv[], which nobody ever ever ever modifies, is not const.Downthrow
P
37

To make sure you don't break stuff, make a copy of the returned string.

The function returning const char* expects this string will never be changed. Therefore things can/will break if your code or the API you pass it make a change after all.

Even worse, if a change is made, your program is likely to crash you in case the returned string was literal (e.g. "hello I'm a literal string") because they are (often) stored in memory that can't be written to.

You could use strdup() for this, but read the small print. Or you can of course create your own version if it's not there on your platform.

Pantia answered 28/8, 2014 at 13:8 Comment(2)
Necro for a response to the question can't you change your code: APIs often require string, char* or const char*, and yeah in theory you could change the entire API, but it's good information to know how to quickly convert itXylo
@Xylo You're right, APIs can't often be changed (I think wrote that in error). Removed that part of my answer. Thanks!Pantia
G
81

First of all you should do such things only if it is really necessary - e.g. to use some old-style API with char* arguments which are not modified. If an API function modifies the string which was const originally, then this is unspecified behaviour, very likely crash.

Use cast:

(char*)const_char_ptr
Goliard answered 28/8, 2014 at 13:7 Comment(6)
I think this answer as it is encourages too much a dangerous practice. It could be improved by making the warnings about undefined behaviour clearer and stronger. At the moment I think many readers will just read the first 2 lines and not notice the important warnings.Spectacle
Now warnings are first and the answer later.Goliard
Or at least use const_cast<char*> so the compiler knows too.Montana
@Montana No such thing as const_cast in C.Goliard
My C++ is rusty but wouldnt this cause issues, when it goes out of scope?Clustered
@Rika Your comment is not very clear and the discussion is about C not C++. Anyway the answer to question whether casting away constness may introduce problems with scope and lifetime is: no it does not introduce such problems.Goliard
P
37

To make sure you don't break stuff, make a copy of the returned string.

The function returning const char* expects this string will never be changed. Therefore things can/will break if your code or the API you pass it make a change after all.

Even worse, if a change is made, your program is likely to crash you in case the returned string was literal (e.g. "hello I'm a literal string") because they are (often) stored in memory that can't be written to.

You could use strdup() for this, but read the small print. Or you can of course create your own version if it's not there on your platform.

Pantia answered 28/8, 2014 at 13:8 Comment(2)
Necro for a response to the question can't you change your code: APIs often require string, char* or const char*, and yeah in theory you could change the entire API, but it's good information to know how to quickly convert itXylo
@Xylo You're right, APIs can't often be changed (I think wrote that in error). Removed that part of my answer. Thanks!Pantia
B
32

You can use the strdup function which has the following prototype

char *strdup(const char *s1);

Example of use:

#include <string.h>

char * my_str = strdup("My string literal!");
char * my_other_str = strdup(some_const_str);

or strcpy/strncpy to your buffer

or rewrite your functions to use const char * as parameter instead of char * where possible so you can preserve the const

Bowne answered 28/8, 2014 at 13:11 Comment(5)
strdup is a non standard implemantation. So you shouldn't be sure he "can use it"Liaoyang
Implementing a missing strdup() is a matter of 15 minutes.Intact
@Intact of course. But as the OP is catching such a problem and is asking for a solution, it is posibbly not a solution for him "implementing strdup by your self" ya know?Liaoyang
@Zaibis: if (constptr) {char * p = calloc(strlen(constptr)+1, sizeof(*constptr)); if (!p) fail(); strcpy(p, constptr); my_nonconstptr_func(p); free(p);}Intact
@Intact well, now we have the implementation. Doesn't change anything on my statement. ;)Liaoyang
S
7

A const to a pointer indicates a "read-only" memory location. Whereas the ones without const are a read-write memory areas. So, you "cannot" convert a const(read-only location) to a normal(read-write) location.

The alternate is to copy the data to a different read-write location and pass this pointer to the required function. You may use strdup() to perform this action.

Shier answered 28/8, 2014 at 13:17 Comment(1)
Exactly. const is specified to say that the value remains constant and cannot be further modified.Emiliaemiliaromagna
M
2

To convert a const char* to char* you could create a function like this :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char* unconstchar(const char* s) {
    if(!s)
      return NULL;
    int i;
    char* res = NULL;
    res = (char*) malloc(strlen(s)+1);
    if(!res){
        fprintf(stderr, "Memory Allocation Failed! Exiting...\n");
        exit(EXIT_FAILURE);
    } else{
        for (i = 0; s[i] != '\0'; i++) {
            res[i] = s[i];
        }
        res[i] = '\0';
        return res;
    }
}

int main() {
    const char* s = "this is bikash";
    char* p = unconstchar(s);
    printf("%s",p);
    free(p);
}

Miserere answered 17/4, 2019 at 2:31 Comment(2)
In this code uninitialized variable res is used. This code res[i] = s[i] is undefined behavior, most likely crash.Goliard
Updated Code: Added check for NULL and possibly resolved undefined behavior.Miserere
L
1

You can cast it by doing (char *)Identifier_Of_Const_char

But as there is probabbly a reason that the api doesn't accept const cahr *, you should do this only, if you are sure, the function doesn't try to assign any value in range of your const char* which you casted to a non const one.

Liaoyang answered 28/8, 2014 at 13:9 Comment(2)
the const char* is returned by an objective-C string method[NSString's to be more specific). This is a path of a file which got saved. Now there is another C library's api which will be parsing this file and it only takes char* strings as arguments. Even if i pass the const char* string, the parsing happens but i get a warning which i don't want to see.Hurlee
@Hurlee Anyway, you can't be sure as long you didn't analyze the source by your self.Liaoyang
H
-1

For example, you could write this way:

const char* a = "art.bin";
char* b = new char[sizeof(a)];
strcpy(b, a);
Henni answered 24/7, 2022 at 15:40 Comment(1)
C doesn't have a new operator. Please don't use C++ to answer C questions. Additionally, answers are more useful when they explain things rather than just provide a snippet of code.Astraea

© 2022 - 2024 — McMap. All rights reserved.