当前位置: 首页 > 知识库问答 >
问题:

无法理解表达式如何变得虚假 [重复]

邵亦
2023-03-14
int main( ) 
{ 
      int  k = 35 ; 
      printf ( "\n%d %d %d", k == 35, k = 50, k > 40 ) ; 
} 

上述程序的输出是“0 50 0”,不带引号。我的问题是 k==35k


共有3个答案

益泰平
2023-03-14
匿名用户

这是未定义的行为,这意味着任何事情都可能发生。

为什么是UB?

答案很简单,在写入< code>k和读取< code>k之间没有顺序限制,甚至没有不确定的顺序,后者不用于确定< code>k的新值。

printf ( "\n%d %d %d", k == 35, k = 50, k > 40 );
// No ordering constraint between function arguments.

题外话:如果写入发生在参数列表中调用的函数中(而不是在该函数的参数中),它将是不确定的顺序,因此不是UB。
不确定排序意味着它在之前或之后进行排序,而不确定哪个。它并不像UB那么糟糕(任何事情),但仍然不应该依赖它,因为顺序不可靠。

int SetVar(int *p, int v) {return *p = v;}

printf ( "\n%d %d %d", k == 35, SetVar(&k, 50), k > 40 );
// No ordering constraint between function arguments, but
// the function call is indeterminately ordered

丁景山
2023-03-14

由于参数列表中的赋值,您的代码调用了未定义的行为:

k = 50

您大概想要:

printf("%d %d %d\n", k == 35, k == 50, k > 40);

由于在参数列表中嵌入了赋值,因此任何结果都是允许的。参数没有要求的求值顺序;它们可以按任何顺序进行评估&任何结果都是正确的。为了您自己的理智,永远不要编写依赖于参数求值顺序的代码。

如果你正在学习的书不是简单地强调评估的顺序是未定义的,任何未定义的行为都是不好的,那么你可能应该丢弃这本书。

卫弘懿
2023-03-14

printf调用调用未定义的行为。

函数参数的求值顺序是未指定的行为。这意味着参数可以从一组所有可能的顺序中以任何顺序求值。该标准不要求实现强制执行任何顺序。此外,分隔参数的逗号不是逗号运算符。这意味着参数的求值之间没有序列点。唯一的要求是所有参数必须被完全求值,并且在调用函数之前必须发生所有副作用。现在,C99标准§6.5¶2说

在上一个序列点和下一个序列点之间,对象应通过表达式的求值最多修改一次其存储值。此外,应仅读取先前值以确定要存储的值。

函数参数的求值是无序的。赋值表达式k=50的求值结果为50,但它的副作用是将50赋值给k。如果首先求值此表达式并且其副作用立即发生,则表达式k==35将求值为truek

只需强调一下,代码中未定义的行为并不是因为参数的求值顺序未指定(不是未定义,这是不同的),而是因为参数求值之间没有序列点,因此,在这种情况下,违反了上述引用的标准部分。

未定义的行为意味着代码的行为是不可预测的。任何事情都可能发生,从程序崩溃到你的硬盘被格式化为恶魔从你的鼻子里飞出(以夸张的方式启动)。这只是为了强调标准不要求实现来处理这种情况,你应该永远避免这样的代码。

进一步阅读-

  • 每个C程序员都应该知道的关于未定义行为的知识
  • 未定义的行为和序列点
  • 为什么 f(i = -1, i = -1) 未定义的行为?
  • 评估顺序

 类似资料:
  • 我们使用Spring-boot和Spring-cloud以及Spring-cloud-netflix和Spring-Cloud-Feign。 我们正在创建我们的网关应用程序,在的帮助下,该应用程序将尝试与我们的微服务通信,以验证它们的凭据。在这里,您可以看到我们的假装客户端的一个示例: 最好的,

  • 如何在不包含连续子字符串baa的字母表{a,b,c}上表达正则表达式?

  • 有人能帮我理解为什么我对elasticsearch分析器的理解是错误的吗? 我有一个包含各种字段的索引,特别是: 如下所示: 并且 的理解是,它将标记一个句子,以便在出现任意数量的或或时拆分它们。例如,给定模式,以下句子: 我希望看到: 我可以从https://regex101.com/ 然而,当我对上面的句子运行words\u only\u分析器时: 我得到, 这告诉我句子被标记为: 在我看来,

  • 我有metohod myservice#create,它抛出CustomException。我在可选#map中调用此方法,如下所示: 当我用引起异常的参数调用这个方法时,就会捕获CustomException,但结果是操作成功,状态为200。如何在lambda中处理此异常并返回异常消息?

  • 问题内容: 我正在使用通用表表达式进行分页: 进行此查询后,我立即进行几乎相同的查询以检索项目总数: 我尝试将它们组合在一起(即:定义CTE,查询数据,然后查询Count,但是当我这样做时,响应第二个查询(Count),我收到一条错误消息“ Invalid object name’query’” )。 有什么方法可以将这两个查询合并为一个,以节省往返数据库的费用? 问题答案: 如果您在2个不同的查