Reputation: 33678
Edit: After asking this question I was informed about the question How to initialize a char array without the null terminator? which is almost identical. (I'm building a network packet as well.)
I'll keep this question open anyway, because I'm just assigning and not initializing.
I have a fixed size array that I would like to assign a fixed text to:
char text[16];
text = "0123456789abcdef";
Of course this doesn't work because the right hand side contains the null terminator.
error: incompatible types in assignment of 'const char [17]' to 'char [16]'
The text is human-readable, so I would prefer to keep it in one piece, i.e. not write {'0', '1', ...}
.
Can I make the assignment work somehow?
By the way, I only have a few hundred bytes of RAM, so preferably (but second to the human-readability requirement) the solution shouldn't use twice the RAM for a temporary copy or something like that.
Upvotes: 0
Views: 284
Reputation: 2205
First of all, in case you have any misunderstanding -- "0123456789abcdef"
is a string literal. Its type is const char [17]
, not const char [16]
, because this string literal has a null terminator \0
in the end.
Then I assume you do mean assignment not initialization. They are different.
I can think of multiple ways to do the assignment. You may choose based on your needs.
#include <cstddef>
#include <cstring>
#include <iostream>
#include <string>
#include <string_view>
using std::size_t;
template<size_t N>
void print(const char (&a)[N])
{
for (size_t i = 0; i != N; ++i)
putchar(a[i]);
putchar('\n');
}
void foo1()
{
char text[16];
std::memcpy(text, "0123456789abcdef", sizeof text);
print(text);
}
void foo2()
{
char text[16];
std::string("0123456789abcdef").copy(text, sizeof text);
print(text);
}
void foo3()
{
char text[16];
std::string_view("0123456789abcdef").copy(text, sizeof text);
print(text);
}
// programmer needs to make sure access with src is valid
template<size_t N>
void assign(char (& dest)[N], const char * src)
{
for (size_t i = 0; i != N; ++i)
dest[i] = *src++;
}
void foo4()
{
char text[16];
assign(text, "0123456789abcdef");
print(text);
}
int main()
{
foo1(); // 0123456789abcdef
foo2(); // 0123456789abcdef
foo3(); // 0123456789abcdef
foo4(); // 0123456789abcdef
return 0;
}
Some remarks:
std::memcpy
is the traditional memory copy way from Cstd::string_view
is a light-weight view on a string, introduced in C++17assign()
-- with a template you can tell the size of an array at compile time. Depending on your needs, you may decide whether or not to implement bounds checking.Upvotes: 0
Reputation: 832
If you write in C:
char text[16];
strncpy(text, "0123456789abcdef", sizeof(text));
Note that text
will not have the null-terminator and won't be compatible with the standard C functions like strlen
. If the text if human-readable, I recommend to include the terminator. It is only one character but it will make your life much easier.
Example:
char text[17];
strncpy(text, "0123456789abcdef", sizeof(text));
Upvotes: 2