C 中的 +(+k--) 表达式

2023-11-23

我在测试中看到这个问题,我们必须告诉以下代码的输出。

#include<stdio.h>

int main(){
    int k = 0;
    while(+(+k--)!=0)
    k=k++;
    printf("%d\n", k);  
    return 0;
}

输出是-1。但我不确定为什么这是答案。

表达什么意思+(+k--)意思是C语言?


这段代码非常令人困惑,也许是故意的。它包含了一个勉强避免的恐惧实例未定义的行为。很难知道提出这个问题的人是非常非常聪明还是非常非常愚蠢。这段代码可能声称要教给你或测验你的“教训”——即一元加运算符没有做太多事情——我认为,这个教训还不够重要,值得这种颠覆性的误导。

代码有两个令人困惑的方面,即奇怪的情况:

while(+(+k--)!=0)

以及它控制的疯狂语句:

k=k++;

我将首先介绍第二部分。

如果你有一个像这样的变量k如果你想加 1,C 给你的不是一种、不是两种、不是三种,而是四种不同的方法:

  1. k = k + 1
  2. k += 1
  3. ++k
  4. k++

尽管有这样的赏金(或者可能正因为如此),一些程序员还是感到困惑并吐出像这样的扭曲:

k = k++;

如果您无法弄清楚它应该做什么,请不要担心:没有人能做到。该表达式包含两种不同的改变尝试k的值(k =部分,以及k++部分),并且因为 C 中没有规则来说明哪个尝试的修改“获胜”,所以这样的表达式在形式上是不明确的,这不仅意味着它有no定义了含义,但包含它的整个程序是可疑的。

现在,如果你看very仔细观察,你会发现在这个特定的程序中,这一行k = k++实际上并没有被执行,因为(正如我们即将看到的)控制条件最初为 false,因此循环运行了 0 次。所以这个特定的程序可能不会actually是未定义的——但它仍然在病态上令人困惑。

也可以看看这些规范的答案关于此类未定义行为的所有问题。

但你没有问k=k++部分。你问了第一个令人困惑的部分,+(+k--)!=0健康)状况。这看起来很奇怪,因为它is奇怪的。没有人会在真实的程序中编写这样的代码。所以没有太多理由去学习如何理解它。 (是的,这是真的,探索系统的边界可以帮助你了解它的优点,但在我的书中,富有想象力、发人深省的探索与愚蠢、滥用的探索之间有一条界限,这种表达方式显然是错误的该线的一侧。)

无论如何,让我们检查一下+(+k--)!=0。 (这样做之后,让我们忘记这一切。)任何像这样的表达都必须从内到外地理解。我想你知道什么

k--

做。它需要k的当前值并将其“返回”到表达式的其余部分,并且它或多或少同时递减k,即存储数量k-1回到k.

但那又是什么呢?+做?这是unary加,不是二进制加。就像一元减号一样。您知道二进制减法执行减法:表达式

a - b

从 a 中减去 b。你知道一元减号会否定事物:表达式

-a

给出 a 的负数。什么一元+确实是……基本上什么都没有。+a给你a的值,将正值更改为正值,将负值更改为负值。所以表达

+k--

给你任何东西k--给了你,也就是说k的旧值。

但我们还没有完成,因为我们已经

+(+k--)

这只是需要任何东西+k--给了你,并应用一元+再次到它。所以它给你任何东西+k--给了你,无论什么k--给了你,这是k的旧值。

所以最后的条件是

while(+(+k--)!=0)

与更普通的情况完全相同

while(k-- != 0)

会做。 (它也与看起来更复杂的条件做同样的事情while(+(+(+(+k--)))!=0)会做。这些括号并不是真正必要的;它也做同样的事情while(+ +k--!=0)会做。)

甚至弄清楚什么是“正常”状况

while(k-- != 0)

确实有点棘手。此循环中发生了两件事:由于循环可能运行多次,因此我们将:

  1. 继续k--, 使k越来越小,而且还
  2. 继续执行循环体,无论它做什么。

但我们做的是k--在决定是否再次进行循环之前(或过程中)立即部分。请记住k--“返回”旧值k,然后递减它。在这个程序中,初始值为k is 0. So k--将“返回”旧值 0,然后更新k至-1。但剩下的条件是!= 0——事实并非如此0 != 0。也就是说,0is等于 0,因此我们不会执行任何循环,因此我们不会尝试执行有问题的语句k=k++ at all.

换句话说,在这个特定的循环中,虽然我说“有两件事正在发生”,但事实证明,事情 1 发生了一次,但事情 2 发生了零次。

无论如何,我希望现在已经足够清楚为什么程序的这个糟糕借口最终会打印 -1 作为最终值k。通常,我不喜欢回答这样的测验问题——这感觉就像作弊——但在这种情况下,因为我根本不同意整个练习的要点,所以我不介意。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C 中的 +(+k--) 表达式 的相关文章

随机推荐

  • 在 F# 中实现队列类型

    我正在尝试在 F 中实现一个队列 到目前为止 这就是我所拥有的 但我认为它的行为更像是一个堆栈 type a queue NL Que of a a queue let enque m function NL gt Que m NL Que
  • appsettings.json 中 IncludeScopes 的 JSON 验证失败

    我正在使用 ASP NET Core 2 1 为什么我得到Expression must be of type object for IncludeScopes in my appsettings json file 下面是显示警告所需的
  • window.orientation 在 iOS 和 Android 中返回不同的值

    我正在测试我的网络应用程序iPad Safari 浏览器 and 三星 Tab 2 默认浏览器 The window orientationchange在两个设备中返回不同的值 document ready function window
  • 在“docker exec”命令中执行“bash -c”

    Context 我正在尝试为我的日常使用编写一个快捷方式docker exec命令 由于某些原因 我正在尝试这样的问题 当我在容器内使用 bash 控制台时 我的输出有时会被破坏 历史记录混乱 行在我编写时相互覆盖 I read here您
  • 什么时候不应该关闭 php 文件?

    我遇到过一个教程 如果我可以添加的话 这是一个有信誉的教程 其中关闭 php 标签 gt 被省略了 这让我想起了之前的一个教程 作者说它实际上更好not关闭标签 但没有解释原因 我有点惊讶 我认为关闭标签是更好的做法 为什么最好不要关闭它
  • 如何访问类中的全局环境对象?

    我有一个类需要更新全局环境对象 我可以整天在结构之间传递该环境对象 但是如何允许类对象访问同一变量 import SwiftUI class Global ObservableObject Published var num 10 clas
  • AWS Athena (Presto)如何将映射转置为列

    AWS Athena 查询问题 我的行中有一个嵌套映射 我想将其中的键转置到列 我可以明确地命名这些列 例如items label a 但在这种情况下 键实际上是动态的 从这些行 id 1 items label a foo label b
  • 需要贵金属 API/Web 服务 [已关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 是否有免费的网络服务 AP
  • JavaMail 按 ReceivedDate 搜索,不能精确到秒吗?

    在 IMAP 中 邮件编号基于邮件放入文件夹的时间 即文件夹中的第一封邮件为 1 第二封邮件为 2 等等 但是 此排序不考虑消息的接收日期 我担心的是早于文件夹中的消息号 1 的消息 即由用户手动移入文件夹的消息 而不是在系统接收到消息时
  • Matplotlib,添加多行文本。添加可以跟随曲线的文本

    我已将文本添加到绘图中 在每行中进行编码 然后调整它看起来不错 增加或减少宽度 或更改位置 但是 有没有办法让 Python 知道您想要文本的位置以及如何设置它 然后我可以添加文本 Python 将计算出详细信息 例如 看看下面的图片 在图
  • 在 Android 中的按钮上写入多行文本

    我想知道如何在按钮上编写多行文本
  • 如何在 Laravel 5.4.18 中使用特征?

    我需要一个示例来说明在何处准确创建文件 写入文件以及如何使用特征中声明的函数 我使用 Laravel 框架 5 4 18 我没有更改框架中的任何文件夹 所有内容都在其对应的位置 已经非常感谢了 我在我的目录中创建了一个 Traits 目录H
  • Promises,如何将变量传递到 .then 函数

    您好 这是一个帮助我理解 Promise 的问题 then返回工作 问题是 如何将变量的作用域限定为第二个 then 链函数 这是一个jsbinhttp jsbin com xacuna edit js 输出 我可以访问全局变量 并将作用域
  • 在特定时间设置 Android 闹钟

    我在特定时间设置了闹钟 但每次我打开应用程序时它都会打开 这是我使用的代码 AlarmManager alarmManager AlarmManager getSystemService Context ALARM SERVICE Inte
  • 文章中的交叉引用

    该书册为方程 图形 表格和章节提供了很好的交叉引用选项 https bookdown org yihui bookdown cross references html 但是 当我设置为输出 articles elsevier article
  • Springs @RequestParam 注解的内部工作原理

    在 Spring 中 如果我没记错的话 以下两个语句是相同的 RequestParam type String type RequestParam String type spring如何知道 type 的变量名 第二版 我当时的印象是 该
  • 同一页面上的多个socket.io连接

    我可以在客户端连接到同一 IP 和端口上的多个资源吗 我有以下代码 var myIP 192 168 1 1 var myPort 8080 A io connect myIP myPort resource A socket io B i
  • 戈多3.2.1。刷新查询时无法更改此状态。使用 call_deferred() 或 set_deferred() 来更改监控状态

    在我的 2D 游戏中 玩家能够摧毁箱子 具有两种碰撞形状的物体 当被摧毁时 板条箱会产生也具有碰撞形状的物品 但是当调用以下函数时 Godot控制台中会显示许多类似的错误 Code func on Crate item dropped co
  • Laravel 5.2 会话 flash 即使使用 Web 中间件也无法工作

    我正在尝试使用会话来实现 Flash 消息传递 但无法做到这一点 在我的控制器中我有 public function store Request request session gt flash donald duck session gt
  • C 中的 +(+k--) 表达式

    我在测试中看到这个问题 我们必须告诉以下代码的输出 include