用于查找数字阶乘的递归函数

2023-12-20

我得到的输出为 24,这是 4 的阶乘,但我应该得到 5 阶乘的输出,即 120

#include <stdio.h>
int factorial(int number){
    if(number==1){
        return number;
    }
    return number*factorial(--number);
}
int main(){
    int a=factorial(5);
    printf("%d",a);
}

你的程序遭受了未定义的行为.

在第一次通话中factorial(5),你在哪里有

return number * factorial(--number);

你想象这会计算

       5      * factorial(4);

但这并不能保证!
如果编译器以不同的顺序查看它怎么办?
如果先在右侧工作怎么办?
如果它首先执行相当于:

temporary_result = factorial(--number);

然后进行乘法:

return number * temporary_result;

如果编译器按照这个顺序执行,那么temporary_resultfactorial(4),它会返回 4 倍,这不会是5!。基本上,如果编译器按照这个顺序执行它 - 它可能会! - 然后number“太快”减少。

您可能没有想到编译器可以这样做。
您可能会想象该表达式总是“从左到右解析”。
但这些想象并不正确。
(也可以看看这个答案 https://stackoverflow.com/questions/31087537/why-does-a-b-have-the-same-behavior-as-a-b/31088592#31088592有关评估顺序的更多讨论。)

我说过该表达式会导致“未定义的行为”,这个表达式就是一个典型的例子。这个表达式未定义的原因是它内部发生了太多的事情。

表达方式有问题

return number * factorial(--number);

是这个变量number在其中使用它的价值,and同一个变量number也在其中进行修改。这种模式基本上是毒药。

让我们标记两个位置number出现了,这样我们就可以非常清楚地谈论它们:

return number * factorial(--number);
       /* A */             /* B */

在 A 点我们取变量的值number.
在 B 点我们修改变量的值number.
但问题是,在 A 点,我们得到的是“旧”值还是“新”值number?
我们是在 B 点修改之前还是之后得到的?

正如我已经说过的,答案是:我们不知道。 C中没有规则告诉我们。

同样,您可能认为存在从左到右评估的规则,但事实并非如此。因为没有规则说明应该如何解析这样的表达式,所以编译器可以做任何它想做的事情。它可以以“正确”的方式或“错误”的方式解析它,或者它可以做一些更奇怪和意想不到的事情。 (而且,实际上,首先没有“正确”或“错误”的方法来解析这样的未定义表达式。)

解决这个问题的方法是:不要这样做!
不要在只有一个变量的地方编写表达式(例如number) 既被使用又被修改。
在这种情况下,正如您已经发现的,有一个简单的修复方法:

return number * factorial(number - 1);

现在,我们实际上并没有尝试修改变量的值number(如表达式--numberdid),我们只是在将较小的值传递给递归调用之前从中减去 1。 所以现在,我们没有违反规则,我们没有使用和修改number在同一个表达中。 我们只是使用它的值两次,这很好。

有关此类表达式中未定义行为的更多信息(更多!),请参阅为什么这些构造使用增量前和增量后未定义的行为? https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior

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

用于查找数字阶乘的递归函数 的相关文章

  • 结构体如何存储在内存中?

    我有一个struct iof header在我的代码中 我确定它的宽度是 24 字节 我执行 sizeof iof header 它返回 32 字节宽 问题1为什么是 32 字节宽而不是 24 字节宽 问题2包括其成员在内 结构体如何存储在
  • 是否有可能劫持标准输出

    我正在尝试使用 C 重定向 Windows XP 上已运行进程的标准输出 我知道如果我自己生成进程 我可以做到这一点 但对于这个应用程序 我更喜欢一个 监听器 我可以附加到另一个进程 这在纯 Net 中可能吗 如果不可能 在 Win32 中
  • 生成多个随机数

    我想生成 25 个唯一的随机数并将它们列在控制台中 数字的长度应至少为 10 个字符 有什么简单的方法可以做到这一点吗 尝试将数字构建为字符串 并使用 HashSet 确保它们是唯一的 Random random new Random Ha
  • NDK 应用 onDestroy 清理 - 如何 DetachCurrentThread

    因此 如果我们连接 我们必须在完成后分离线程 对吗 JNIEnv get jni env JNIEnv res JAVA VM gt GetEnv void res JNI VERSION 1 6 Using cached JavaVM J
  • 将字符串作为 PChar 从 CSharp 传递到 Delphi DLL

    我正在尝试将字符串从 C 传递到 Delphi 构建的 DLL Delphi DLL 需要 PChar 这是Delphi导出 procedure DLL Message Location PChar AIntValue integer st
  • 警告 C4800:“int”:强制值为 bool“true”或“false”(性能警告)

    我的代码中有这个问题 bool CBase isNumber return id MID NUMBER bool CBase isVar return id MID VARIABLE bool CBase isSymbol return i
  • 如何在C中同时运行两个子进程?

    所以我开始学习并发编程 但由于某种原因我什至无法掌握基础知识 我有一个名为 fork c 的文件 其中包含一个 main 方法 在此方法中 我将 main 分叉两次 分别进入子进程 1 和 2 在孩子 1 中 我打印了字符 A 50 次 在
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • 如何减少 MinGW g++ 编译器生成的可执行文件的大小?

    我有一个简单的 Hello world C 程序 在 Win XP 下由 MinGW g 编译器编译为 500kB 可执行文件 有人说这是由于iostream的库和静态链接libstdc dll Using s链接器选项有点帮助 减少了 5
  • 控制台应用程序中使用 Unicode 字符的 _tprintf

    我正在从 Unicode 构建的控制台应用程序 使用 C 和 Visual Studio 2008 执行这个简单的输出 此代码旨在在 Windows 上运行 tprintf L Some sample string n 一切正常 但是如果我
  • 我在使用 ado.net 时收到错误 Argument 2 may not be pass with ref keywords

    int t 0 cmd Parameters AddWithValue Res ref t 我在第二行收到错误 参数 2 不能与 ref 关键字一起传递 您只能通过引用传递参数ref if the 范围 is a ref参数也是如此 Add
  • 如何构建一棵与或树?

    我需要一个支持 与 和 或 的树结构 例如 给定一个正则表达式 如ab c d e 我想把它变成一棵树 所以 一开始我们有两个 或 分支 它可以向下ab or c d e 如果你低头ab分支 你得到两个节点 a and b or a其次是b
  • Gremlin.net 文本包含等效项

    我正在使用 Gremlin net 库连接到 janus 图形服务器 我使用 cassandra 和弹性搜索进行数据存储和索引 在我使用的 gremlin 语言和 gremlin 控制台中文本包含在属性的文本中进行搜索 我正在使用混合索引
  • 选择合适的IDE

    您会推荐使用以下哪种 IDE 语言来在 Windows 下开发涉及识别手势并与操作系统交互的项目 我将使用 OpenCV 库来执行图像处理任务 之后 我将使用 win32 API 或 NET 框架与操作系统交互 具体取决于您建议的工具 性能
  • 连接到没有元数据的网络服务

    我想连接到此网络服务 https training api temando com schema 2009 06 server wsdl https training api temando com schema 2009 06 serve
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO
  • 如何从 Access 数据库中读取“是/否”值作为布尔值?

    帮我找回YES NO来自 MS Access 的布尔格式数据类型 我尝试解析它 但它总是返回 false 更新 实际上不是问题抱歉 它确实接受 YES NO 作为布尔值 OleDbconnection dbConnect new OleDb
  • C 变量声明的效率 [重复]

    这个问题在这里已经有答案了 例如 在 C 中声明一个变量需要多长时间int x or unsigned long long var 我想知道它是否会让我的代码在类似的事情中更快 for conditions int var 0 code 这
  • “1个未解决的外部”C++

    我已经检查了所有文件之间的连接以及类和函数定义 但每次我尝试运行我的程序时 它都会阻止我并告诉我它有 1 个未解析的外部 该程序应该打开多个文件 一个 学生 文件和一个 成绩 文件 从中读取数据 然后使用 查询文件 来查找数据 找到查询中要
  • 实体框架代码首次日期字段创建

    我正在使用实体框架代码优先方法来创建我的数据库表 下面的代码 创建一个DATETIME数据库中的列 但我想创建一个DATE柱子 DataType DataType Date DisplayFormatAttribute ApplyForma

随机推荐

  • 通过FTP协议将文件复制到远程服务器

    我使用 Filezilla 执行 FTP 职责 但如果不将文件复制到本地计算机 则无法复制文件 我怀疑 Filezilla 是个糟糕的软件 这只是FTP的固有品质吗 The FTP协议 http en wikipedia org wiki
  • PHP:函数中的 $_GET 和 $_POST?

    我对代码感到惊讶 其中 GET 值 例如 GET username 不作为函数的参数包含在内 什么时候需要包含 POST 和 GET 方法作为函数的参数 什么时候需要包含 POST 和 GET 方法作为参数 功能 我会说 永远 GET an
  • php如何测试文件是否已完全上传

    有没有办法检查文件是否已完全上传到服务器 我的场景 用户通过 ftp 上传文件 我的其他 PHP 任务在 cronjob 中运行 现在我想检查文件是否已上传或用户是否仍在上传 这很重要 因为这样我就知道我是否可以使用该文件或等到它上传 谢谢
  • 有没有办法在 HTML5 中创建自己的 html 标签?

    我想创建类似的东西 menu menu
  • 为什么 C++11 不能将不可复制的函子移动到 std::function ?

    struct A A A A A operator A return this void operator private A const A A operator const A int x int main A a std
  • C# .NET 中 Windows 窗体之间的值

    我有两种形式 一种是主形式 有一个 crystalreportviewer 另一种形式是用户介绍他想要出现在报告中的用户的 ID 问题我希望用户在报告加载信息之前引入ID 因此当用户在报告加载信息之前单击CreateReport按钮时 我创
  • 如何在java中实现自定义http会话?

    我需要用 Java 实现我自己的 HttpSession 版本 我发现很少有信息可以解释如何实现这一壮举 我想我的问题是 无论应用程序服务器的实现如何 如何覆盖现有的 HttpSession 我确实读过一本高质量但相当老的读物 它帮助我实现
  • 为什么在此表达式中用括号替换美元符号 ($) 会导致错误? [复制]

    这个问题在这里已经有答案了 我有这两种表达方式 foldr 0 map uncurry coords 5 7 foldr 0 map uncurry coords 5 7 1 工作打印出结果 但 2 有错误说
  • 是否可以在不修改/压缩提交的情况下将补丁集添加到 Gerrit 审查中

    一个简单的例子 我对 Gerrit 进行了更改 这会破坏 CI 构建或审阅者不满意 然后我用另一个提交修复我的更改 在许多情况下 这是一个小补丁集 我不希望对其进行新的 gerrit 审查 而是希望将其作为原始审查中的新补丁集 我知道这可以
  • 如何创建动态 LINQ 连接扩展方法

    有一个动态库LINQ http en wikipedia org wiki Language Integrated Query扩展方法作为示例发布Visual Studio 2008 http en wikipedia org wiki M
  • ASP.NET 中的类似 WordPress 的插件框架

    我正在开发一个 CMS 我想要一个框架 这样任何人都可以像 WordPress 一样为其添加插件 我找到了很多解决方案 但它们并没有那么有帮助 谁能告诉我一个好的解决办法吗 Thanks 我可能会首先查看托管可扩展性框架 http www
  • 按住鼠标右键移动无边框 Winform,可能使用本机方法

    我有一种情况 我想通过在窗口的客户区域上按住鼠标右键来移动窗口 正如我所说 它的形式是无边界的 我想 本地 移动它 如果可能的话 否则其他答案也可以 我的意思是当你在标题栏上按住鼠标左键时它的行为方式 通过鼠标移动和类似的事情我得到了很多奇
  • VS Code 有没有办法导入 Makefile 项目?

    正如标题所说 我可以从现有的 Makefile 自动填充 c cpp properties json 吗 Edit 对于其他尝试导入 makefile 的人 我找到了一组脚本 它们完全可以实现我想要实现的目标 即通过 VS Code 管理
  • Java与指纹识别

    有人用Java实现指纹识别系统吗 例如 它附带了适用于 linux 和 windows 平台的 java api http www griaulebiometrics com page en us manual fingerprint sd
  • 为什么 ObservableCollection 不会在项目更改时更新?

    我注意到ObservableCollection在 WPF 中 仅通过添加或删除列表中的项目来反映 GUI 中的更改 而不是通过编辑它 这意味着我必须编写自定义类 ObservableCollection 这种行为的原因是什么 Thanks
  • 强制“git merge”将所有差异声明为合并冲突

    在 git merge 中 我希望任何差异 即使通常不是合并冲突 也被视为合并冲突 然后 通过 git mergetool 我可以看到并解决每个差异 我尝试在 gitattributes 中指定 merge 但这似乎不起作用 git che
  • mysql float 返回错误值

    我有一个高精度值的表 存储为Float 当我在表中查询该值时 它返回四舍五入到第一位数字的四舍五入值 但是当我运行下面的查询时 我得到了我存储的值 SELECT MY FLOAT COL 1 FROM MY TABLE Mysql 内部发生
  • Botframework 提示对话框直到用户完成

    我正在使用 Microsoft 的 botbuilder 和 LUIS 创建一个 slack 聊天机器人 有办法继续使用吗builder Prompts text 不断询问用户是否还有用户想要输入的信息 例如for or while环形 例
  • 如何更改 Visual Studio 中的默认构建输出目录?

    在 Visual Studio 2010 到 2013 中 默认情况下 例如 当我创建新的控制台应用程序时 新解决方案将其编译的可执行文件输出到Solution name Project name bin Debug 我希望它们输出到Sol
  • 用于查找数字阶乘的递归函数

    我得到的输出为 24 这是 4 的阶乘 但我应该得到 5 阶乘的输出 即 120 include