【问题标题】:Using a designated initializer to initialize nested struct with a `char []` member使用指定的初始化程序使用 `char []` 成员初始化嵌套结构
【发布时间】:2020-03-18 19:17:10
【问题描述】:

我有以下嵌套的struct 定义:

typedef struct {
    int count;
    float cash;
    char item[50];//switch between array and pointer for testing initializers
    //char *item;
}Purchase;

typedef struct {
    int accnt;
    char acct_name[50];
    Purchase purch;
} Acct;

对于 Purchase struct 本身,以下初始化程序起作用:

//Uses member names:
/* 1 */Purchase p = {.count = 4, .cash = 12.56, .item = "thing"};
//  Note: this member:                          ^^^^^^^^^^^^^^^

对于嵌套结构Acct,以下工作:

// No member names:
/* 2 */Acct acct = {100123, "Robert Baily", {15, 12.50, "Tires"}};
//                                                      ^^^^^^^

但是当我尝试使用成员名称时,如第一个示例所示:

// Attempts to use member name, but fails the last one:
/* 3 */Acct acct3 = {.accnt = 100123, .acct_name = "Robert Baily", {acct3.purch.count = 15, acct3.purch.cash = 12.50, acct3.purch.item = "Tires"}};
// error occurs here ->                                                                                                                ^

我收到此错误:22, 131 error: array type 'char [50]' is not assignable 使用会员char item[50]; inPurchase时`

我得到这个错误:22, 14 error: initializer element is not a compile-time constantPurchase 中使用成员char *item; 时 (注意任何时候只有一个版本的itemstruct的一部分,其他的被注释掉了)

因此,总而言之,如果不使用上述语句/* 2 */ 中的命名赋值语句,我可以初始化一个嵌套结构,但是当我尝试使用如语句char [] 中所示的命名赋值语句/* 3 */ 中的类型时,它失败了。

char []char * 是嵌套结构构造的内部结构的成员时,我缺少什么初始化?

我正在使用设置为 C99 的 CLANG

【问题讨论】:

  • 为什么不是... {.purch.count = 15, .purch.cash = 12.50, .purch.item = "Tires"}}
  • @DavidC.Rankin - 我确实尝试过。对于这些尝试,我收到错误消息:23, 63 error: field designator 'purch' does not refer to any field in type 'Purchase'。 (即使其他两个成员使用相同的名称。purch.countpurch.cash 没有问题)
  • 是的,让我再仔细看看。我记得这不是很早以前就咬我了,我记得结果是对于嵌套结构,您必须为所有成员提供初始化(尽管标准允许摆动空间),但我必须刷新并查找它。给我几分钟。
  • @DavidC.Rankin - 在我所有的尝试中,我正在初始化所有成员。

标签: c struct nested designated-initializer


【解决方案1】:

您正在尝试编译:

Acct acct3 = {.accnt = 100123, .acct_name = "Robert Baily", 
           {acct3.purch.count = 15, acct3.purch.cash = 12.50, acct3.purch.item = "Tires"}};

此初始化程序无效,因为 acct3.purch 不是 Purchase 的字段名称。初始化时只使用最里面的字段名称。

Acct acct3 = {.accnt = 100123, .acct_name = "Robert Baily", 
              .purch = {.count = 15, .cash = 12.50, .item = "Tires"}};

【讨论】:

  • 你成功了!在发布此问题之前,我曾在第三位成员身上尝试过此操作,但收到了另一条错误消息。我没有认识到错误是指成员 2。(我让成员 2 和成员 1 仍然使用 .purch.cash.purch.count。(我的编译器设置为每个语句只显示一个错误。)
  • 那么,问题:是不是初始化语句中嵌套的{,,,} 允许编译器解决所有歧义?即识别将值应用于哪个结构和哪个成员,即使在两个不同的嵌套结构中可能使用重复的成员名称?
  • @ryyker 由于指定的初始化程序名称被限制在最内部的范围内,因此这些名称仅适用于它们正在初始化的特定类型。其他结构可能具有相同名称的成员这一事实并不重要。
  • 标准的第 6.7.9 节在这里有点不清楚。这个问题似乎是使用 named-initializer 的一个怪癖。没有它,例如{10, "account", {2, 4.6, "item"}} 不需要特殊处理。我仍在寻找一个明确的参考。 (我认为@dbush 刚刚添加了评论)
  • @DavidC.Rankin 如果字段未命名,则初始化按照字段声明的顺序进行。
【解决方案2】:

结构 Acct 和结构 Purchase 都没有数据成员名称 acct3。所以这个变量Acct acct3的初始化列表

{acct3.purch.count = 15, acct3.purch.cash = 12.50, acct3.purch.item = "Tires"}

无效。

考虑到错误消息,编译器会考虑这样的初始化列表的一部分

acct3.purch.item = "Tires"

作为对象 acct3 的数据成员项的赋值,数组没有赋值运算符,因为它们是不可修改的左值。

【讨论】:

  • Acct3 使用 typedef Acct 定义。因此,在这些示例中,Acct3structAcct 实例
  • @ryyker 我没有看到 Acct3。我看到变量 acct3 的使用名称
  • 同意,我在 cmets 中的错误。但是我并没有在代码本身中犯这个错误。我用Acct acct3 = {...
猜你喜欢
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-26
相关资源
最近更新 更多