For the following program:
int main()
{
new char[4] {"text"}; // #1
new char[5] {"text"}; // #2
new char[] {"text"}; // #3
}
clang gives an error for #1
which says:
error: initializer-string for char array is too long
and accepts #2
and #3
.
gcc gives the following error for all statements:
error: invalid conversion from 'const char*' to 'char' [-fpermissive]
and in addition for #3
it gives the error:
error: expected primary-expression before ']' token
So what does the language say about whether this code is well-formed?
I want to know the current rules, but I'd also be interested to know if this has this changed in previous versions of the language.
A character array is a sequence of characters, just as a numeric array is a sequence of numbers. A typical use is to store a short piece of text as a row of characters in a character vector.
In C, an array of type char is used to represent a character string, the end of which is marked by a byte set to 0 (also known as a NUL character)
Initializing Char Array A char array can be initialized by conferring to it a default size. char [] JavaCharArray = new char [ 4 ]; This assigns to it an instance with size 4.
Char array or array of char is used to print or display the sequence of characters or numbers. With the help of a character array, we can store the variable in a memory to a correspondence memory address.
char ary []="Hello..!"; A) Character array, ary is a string. D) String can not contain special characters. It is a simple way of creating a C String. You can also define it like the below. \0 is mandatory in this version. char ary [] = {'h','e','l','l','o','\0'};
4. On the point of array initialization which is required to specify? Row is essential to specify when initializing an array. Example: 5. Which declaration is valid ? As a result, option (A) and option (C) are wrong as parentheses ( ) is used in place of square brackets [ ].
All of the above. Arrays are data structures that may consist of data items of different types. Arrays are data structures consisting of data items of the same type. Nice work! You just studied 25 terms! Now up your study game with Learn mode. Arrays may have __________ dimensions. All of the above.
When values are provided upon declaration of an array, the new keyword is not required. Values in an array can be totaled by using the ArrayTotal method. False. If the values of an array need to be totaled, a repetition statement may be used to traverse the array and add up each element.
OK, this is pretty simple to trace. The presence of {}
means that list initialization is being performed, so we get to visit our favorite part of the spec: [dcl.init.list]/3.
The object being initialized in case 1 is a char[4]
. The braced-init-list is not a designated initializer, so 3.1 is ignored. char[4]
is not a class, so 3.2 is ignored. That brings us to 3.3:
Otherwise, if
T
is a character array and the initializer list has a single element that is an appropriately-typed string-literal ([dcl.init.string]), initialization is performed as described in that subclause.
Well, char[4]
is definitely a character array, and the initializer list definitely contains a single element, and that element does in fact match the type of the character array. So off to [dcl.init.string] we go.
That tells us (after a fashion):
Successive characters of the value of the string-literal initialize the elements of the array.
But the next paragraph warns:
There shall not be more initializers than there are array elements.
Well, that makes #1 ill-formed.
So, we redo the process for char[5]
. And that doesn't trigger, since 5 is sufficiently large.
Lastly, we come to char[]
. Which is no different from using a number, as far as initialization is concerned. char[]
is an array of characters, so it follows the above rules. C++17 would choke on using char[]
in a new
expression, but C++20 is fine with it.
If the type-id or new-type-id denotes an array type of unknown bound ([dcl.array]), the new-initializer shall not be omitted; the allocated object is an array with n elements, where n is determined from the number of initial elements supplied in the new-initializer ([dcl.init.aggr], [dcl.init.string]).
Which means that #2 and #3 are supposed to be legal. So GCC is wrong to make them ill-formed. And it makes #1 ill-formed for the wrong reason.
Clang is correct in that #1 is ill-formed and #2 is okay.
As Ted Lyngmo noted in a comment, #3 was invalid by the C++ grammar rules, until paper P1009R2 made a change to allow it. A new-expression simply did not allow the possiblity of empty []
in the type, left over from when there was no syntax to initialize the array created by a new-expression, and therefore no way for a compiler to determine the actual size. The paper's changes are accepted in C++20 (but compiler writers will sometimes choose to support "fixes" retroactively in previous -std=
modes).
For the difference between #1 and #2, the initialization of the array object is specified in [expr.new] to follow the direct-initialization rules of [dcl.init]. The general rules for initialization in [dcl.init] early on say if the initializer is a braced-init_list, it is list-initialization. The rules for this in [dcl.init.list] go like:
List-initialization of an object or reference of type
T
is defined as follows:
[C++20 only:] If the braced-init-list contains a designated-initializer-list, ...
If
T
is an aggregate class and...Otherwise, if
T
is a character array and the initializer list has a single element that is an appropriately-typed string-literal ([dcl.init.string]), initialization is performed as described in that subclause....
And so [dcl.init.string] (C++17, latest) gives the actual initialization rules which apply to this code:
An array of {C++17: narrow character type}{C++20: ordinary character type ([basic.fundamental])},
char8_t
array,char16_t
array,char32_t
array, orwchar_t
array can be initialized by {C++17: a narrow}{C++20: an ordinary} string literal, UTF-8 string literal, UTF-16 string literal, UTF-32 string literal, or wide string literal, respectively, or by an appropriately-typed string-literal enclosed in braces ([lex.string]). Successive characters of the value of the string-literal initialize the elements of the array.There shall not be more initializers than there are array elements. [ Example:
char cv[4] = "asdf"; // error
is ill-formed since there is no space for the implied trailing
'\0'
. — end example ]If there are fewer initializers than there are array elements, each element not explicitly initialized shall be zero-initialized ([dcl.init]).
Just like the plain variable definition, when the character array type of a new-expression has a specified bound, it must be large enough for all the characters of a string literal initializing it, including the trailing null character.
(This is an old difference between C and C++: C does allow char cv[4] = "asdf";
and ignores the null character.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With