【问题标题】:Precedence of assignment [duplicate]分配的优先顺序[重复]
【发布时间】:2017-06-26 14:00:45
【问题描述】:

在 c 中,

main()   {
 int a = (1,2,3,4);
  printf("%d",a); 
}

产生

的输出

4

这是因为 comma(,) 运算符具有从右到左的优先级。 但是

main()   {
int a = {1,2,3,4};
 printf("%d",a);
}

产生一个输出

1

请任何人解释这背后的逻辑。 谢谢

【问题讨论】:

  • gcc -Wall 告诉你什么?
  • 我认为这是constraint violation,因此是未定义的行为。
  • 这一切看起来都不是标准的,截至 2017 年或过去 30 年也不正确。
  • 实际上完全没问题 C. 几乎完全相同的副本:stackoverflow.com/questions/35266987/…
  • @Lundin(替换评论)——我看到它正在尝试对指针执行此操作,但此问题并未讨论是否允许这样做。看看我的回答,我对 §6.7.9 -- 2 的解释错了吗?

标签: c operators


【解决方案1】:

{1,2,3,4}initializer 的语法,用于初始化具有多个值的东西,例如数组或结构。所以里面的逗号不是运算符,它们只是初始化语法的一部分。

初始化时,C 使用初始化器中的值从左边。初始化单个标量变量时,只需要一个元素。

你的编译器应该告诉你这段代码没有意义:

x.c:2:12: warning: excess elements in scalar initializer
 int a = {1,2,3,4};
            ^

我应该补充一点,该代码违反了标准的约束,请参阅 C11 草案 N1570,§ 6.7.9 -- 2:

任何初始化器都不应尝试为未包含在正在初始化的实体中的对象提供值。

这要求编译器在编译此类损坏的代码时发出诊断信息。

来自同一段落的以下规则(第 17 条):

每个用大括号括起来的初始化器列表都有一个关联的当前对象。没有时 指定存在,当前对象的子对象按顺序初始化 到当前对象的类型:下标递增顺序的数组元素,结构 声明顺序的成员,以及联盟的第一个命名成员。1

因此,您的编译器决定按照标准执行“下一个最接近”的操作,并且只使用您提供的第一个值。

【讨论】:

  • gcc 即使没有 -Wall 选项也会发出警告。
  • @Jean-FrançoisFabre 必须这样做(违反约束),我刚刚更新了我的答案。
【解决方案2】:

这是一个initializer(通常用于数组),但你没有明智地使用它,你的编译器没有告诉你吗?

Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c 
main.c:2:13: warning: excess elements in scalar initializer
 int a = {1,2,3,4};
            ^

这里的优先级是从左到右,因为你只有一个元素要初始化,所以从初始化器中选择一个元素(在本例中为 1)。

【讨论】:

    【解决方案3】:

    花括号表示变量的初始化,主要用于数组

    在您的情况下,使用 gcc 进行编译会产生:

    test.c:6:12: warning: excess elements in scalar initializer
     int a = {1,2,3,4};
                ^
    

    (3 和 4 相同)

    意味着只有值 1 对您的情况有用(它是一个标量)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-04
      • 2021-02-28
      • 1970-01-01
      • 2019-03-21
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      相关资源
      最近更新 更多