The following two codes behave as expected:
char* test1 = new char[20]{"abc"};
cout << test1;
Outputs: abc
int size = 20;
char* test1 = new char[size]{'a','b','c'};
cout << test1;
Outputs: abc
But, the following code behaves unexpectedly in gcc and MSVC, while not in clang:
int size = 20;
char* test1 = new char[size]{"abc"};
cout << test1;
Outputs: random values
Why does it not output abc
like the other examples?
This is clearly a GCC and MSVC bug, although I could not find an existing bug report for it. Clang seems to handle it properly.
Note that there exists wording to cover this case in [expr.new] p8:
If the expression in a noptr-new-declarator is present, it is implicitly converted to
std::size_t
. The value of the expression is invalid if
- [...]
- the new-initializer is a braced-init-list and the number of array elements for which initializers are provided (including the terminating
'\0'
in a string-literal ([lex.string])) exceeds the number of elements to initialize.
What you are doing is expected and valid; the expression size
is present, and "abc"
only provides an initializer for four elements (including the terminating '\0'
), which does not exceed the 20
elements you're constructing.
The initialization follows the rules in [dcl.init.string], which covers both "abc"
and {"abc"}
. The remaining 16 elements of the array should be zero.
You should consider using std::string
or performing the initialization in two steps:
new char[size]{}
, leaving everything zero initiallystd::memcpy
the string literal into the char*