简体   繁体   中英

How can I convert const char* to char[256]

How do I convert const char* to char[256] ?

const char *s = std::string("x").c_str();
char c[256] = /* ??? */

You cannot initialise an array with a character pointer. But you can copy the string. For example:

const char *s = get_the_string();
char c[256]{};
auto n = std::strlen(s);
if (std::size(c) <= n)
    throw std::runtime_error(
        "The buffer is too small. Contact your local C++ maintainer");
std::memcpy(c, s, n);

The obvious problem with using an array of constant size is that you need to consider how to handle situation where the input string doesn't fit. Here, I've used an exception, but you can use error handling of your choice, if this is not an option for you.


You cannot copy from a const char *s = std::string("x").c_str(); though, because the pointer is dangling, and attempting to access the pointed data would have undefined behaviour.

Copying the contents from the const type to an editable one is really your only recourse for dropping the const. I'm guessing you are given a const because something has marked it "not ok for you to change" ie read only.

The trouble with a pure * though is you need to know how long it is. For null-terminated strings, strlen can get you that size (and so it works with strncpy).

strncpy(c,s,256);

If the const char * were just bytes though, you'd need another way.

There are many different ways to copy a const char* into a char[] :

#include <cstring>
const char *s = "x";
char c[256]{};
std::strncpy(c, s, 255);
#include <algorithm>
#include <cstring>
const char *s = "x";
char c[256]{};
std::copy_n(s, std::min(std::strlen(s), 255), c);
#include <string>
const char *s = "x";
char c[256]{};
std::string(s).copy(c, 255);
#include <sstream>
const char *s = "x";
char c[256]{};
std::istringstream iss(s);
iss.read(c, 255);
//or: iss.get(c, 256, '\0');

strncpy(c, s, 256); it work for me

As others have pointed out

const char *s = std::string("x").c_str();

Is bad code. It effectively creates a new string, puts "x" in it, returns a pointer to "x", frees the string. So now what s points to is undefined

If you were not creating the string in that line it would be safe. For example

const auto t = std::string("x");
const char *s = t.c_str();

Now t will be valid until the current scope exits and so will s

As for the copy to an array of 256 characters the arguably optimal solution is

char c[256];
std::strncpy(c, s, 255);
c[255] = '\0';

Why?

This line

char c[256];

allocates space on the stack for 256 bytes and does nothing else.

This line

std::strncpy(c, s, 255);
  • if s is less than 255 characters it copies those characters into c then writes out zeros to pad out the buffer to the 254th element
  • if s is 255 characters or more it just copies the first 255 characters

This line puts a null terminating zero at the end

c[255] = '\0';

Let's compare to other solutions

This one

    char c[256];
    std::strncpy(c, s, 256);

Problem with this answer is if s is more than 255 characters there will be no terminating 0 at the end of c . Whether that's important or not is really up to you but 999 times out of 1000 it probably is important.

This one

    char c[256]{};
    std::strncpy(c, s, 255);

Is safe but slower. The difference is the {} at the end of char c[256]{} . Without that {} the c array is only allocated. With it c is not only allocated but also initialized to 0 for all 256 characters. That means for every character copied from s to c there was a wasted effort clearing the character to zero at the beginning. That's potentially double the work

const char *s = get_the_string();
char c[256]{};
auto n = std::strlen(s);
if (std::size(c) <= n)
    throw std::runtime_error(
        "The buffer is too small. Contact your local C++ maintainer");
std::memcpy(c, s, n);

Same as above, does double the work though it is good to point out that you must choose how to handle s being too big to fit in c .

All of the examples using char c[256]{} instead of char c[256] are potentially doing double the work. Doing double the work is not necessarily bad but given the optimal version is simple there's no reason not to use it.

One other issue is using magic numbers. Unfortunately C++ didn't add an array size function until C++ 17 (std::size) so we're left to make our own

template<class T, size_t N>
constexpr size_t array_size(T (&)[N]) { return N; }

so then we can do this

char c[256];
std::strncpy(c, s, array_size(c) - 1);
c[array_size(c) - 1] = '\0';

so now if we change the size of c the code will still work.

The standard version for getting the number of elements in an array is std::size added in C++ 17 but C++ 17 is apparently still rare, none of the online C++ compilers I tried (first several hits in Google) supported it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM