C++20指定初始化器char[]

3

C++20引入了指定初始化器。我正在尝试使用新语法来初始化结构体中的字符数组。

问题非常简单,我认为最好通过代码来解释

struct Test
{
    unsigned v;
    char b[12];
};

int main()
{
    char str[12] = "hello"; // Works.
    char strb[12]{"hello"}; // Works.
    //
    Test testa
    {
        .v = 100u,
        .b = "hello" //Doesn't work...
    };
    Test testb
    {
        .v = 100u,
        .b = { "hello" } //Doesn't work...
    };
    Test testc
    {
        .v{ 100u },
        .b{ "hello" } //Doesn't work...
    };
    Test testd
    {
        .v{ 100u },
        .b{ "hello" } //Doesn't work...
    };
    Test teste
    {
        .v = 100u,
        .b = {} //This works.
    };
    Test testf
    {
        .v = 100u,
        .b = {'h', 'e', 'l', 'l', 'o', '\0'} //This works.
    };
    return 0;
}

我觉得这种行为很奇怪,char str[12] = "hello"; 这一行可以正常工作。但是在指定初始化器列表中相同的初始化形式却不起作用。 问题: 为什么我不能使用字符串字面值初始化字符数组? 编辑 之前我使用的是GCC。 这在clang中可行。 是否有GCC的解决方法,clang或GCC哪个正确?

1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55227 - cpplearner
1
因此,GCC拒绝Test testa { .v = 100u, .b = "hello" };但在非严格模式下接受Test testa { .v = 100u, { .b = "hello" } };,这显然是荒谬的。 - cpplearner
有趣,听起来像是编译器的错误... 感谢提供相关链接! - David Ledger
2个回答

2
指定初始化器是聚合初始化的轻微变体。指定程序名称的唯一用途是决定从给定的花括号或等号初始化程序中初始化哪个聚合成员。指定初始化的使用对于初始化的特定形式没有任何影响,因此,无论它是否有效,都不会改变任何东西。

考虑你的Test对象,Test{100u, "hello"}Test{.v = 100u, .b = "hello"} 要么都有效,要么都无效。在两种情况下,Test::b 都与 [dcl.init.aggr]4.2 相符合地进行了初始化:

否则,元素将从相应的初始化程序子句复制初始化,或使用相应的指定初始化程序子句的花括号或等号初始化程序进行初始化。

复制初始化的过程与如果您仅初始化数组变量时完全相同。这是完全有效的。

因此,你的代码应该可以工作。这是一个编译器错误。

GCC的“解决方法”是等待修复该错误。或者在他们的编译器被修复之前回到标准的聚合初始化。

我希望我错了,可以继续前进。我已经点赞了,但是可能有人会有一个有趣的语法解决方法,所以我会延迟选择你的答案 :) - David Ledger

0

我认为你不能这样初始化它,因为它们不兼容。如果从严格的层面来看...或者说是“追求完美”的层面 ;)

即使它们密切相关,char数组也不等于std::string。为了类型安全,编译器禁止这种赋值。
甚至{{link1:char数组和char*也不相同}},正如Geeks for Geeks所解释的那样。

我在这里看不到任何荒谬之处...也许有些东西我忽略了?

你发布的规范在底部的“注释”部分中说明:

在C中,大小比字符串字面量小一个字符的字符数组可以从字符串字面量初始化;结果数组没有以null结尾。在C++中不允许这样做。

我认为这解释了一切。但我同意,它有点“隐蔽”。


1
谢谢。但我指的不是std::string,而是字符数组。我认为这段引用只涉及使用字符串字面值初始化数组时会丢失空字符的情况。 因此,当空字符被丢弃时,C ++不允许初始化char数组。 - David Ledger
我提到了std:string,是因为你在初始化时使用了字符串字面量,并且怀疑存在类型不匹配的问题,因为gcc可能会将char[] b和"hello"解释为<array>和std:string类型,从而阻止该初始化...但这实际上与您发布的C++20规范相矛盾...我很无助,实际上我的帖子已被删除。我不知道为什么它仍然出现。尽管如此,感谢您的友善言辞和解释。 - Antares

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接