使用 goto 跳过变量声明?

2024-04-26

我在读C 编程 - 现代方法由 K.N.King 学习 C 编程语言,并指出goto语句不得跳过可变长度数组声明。

但现在的问题是:为什么goto跳转允许跳过​​固定长度数组声明和普通声明吗?更准确地说,根据 C99 标准,此类示例的行为是什么?当我测试这些情况时,似乎声明实际上没有被跳过,但这是正确的吗?其声明可能已被跳过的变量可以安全使用吗?

1.

goto later;
int a = 4;
later:
printf("%d", a);

2.

goto later;
int a;
later:
a = 4;
printf("%d", a);

3.

goto later;
int a[4];
a[0] = 1;
later:
a[1] = 2;
for(int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
  printf("%d\n", a[i]);

我很想在没有血淋淋的内存布局细节的情况下解释这一点(相信我,他们得到very使用 VLA 时的血淋淋;有关详细信息,请参阅@Ulfalizer 的答案)。

因此,最初,在 C89 中,必须在块的开头声明所有变量,如下所示:

{
    int a = 1;
    a++;
    /* ... */
}

这直接暗示了一件非常重要的事情:一个块==一组不变的变量声明。

C99改变了这一点。在其中,您可以在块的任何部分声明变量,但声明语句仍然与常规语句不同。

事实上,为了理解这一点,您可以想象所有变量声明都隐式移动到声明它们的块的开头,并且对于它们之前的所有语句都不可使用。

那只是因为一个块 == 一组声明规则仍然成立。

这就是为什么你不能“跳过声明”。声明的变量仍然存在。

问题是初始化。它不会被“移动”到任何地方。因此,从技术上讲,对于您的情况,以下程序可以被认为是等效的:

goto later;
int a = 100;
later:
printf("%d", a);

and

int a;
goto later;
a = 100;
later:
printf("%d", a);

正如你所看到的,声明仍然存在,只是跳过了初始化。

这不适用于 VLA 的原因是它们是不同的。简而言之,这是因为这是有效的:

int size = 7;
int test[size];

与所有其他声明不同,VLA 的声明在声明它们的块的不同部分中表现不同。事实上,VLA 可能具有完全不同的内存布局,具体取决于它的声明位置。你只是无法将它“移动”到你刚刚跳过的地方之外。

你可能会问:“好吧,那为什么不这样做,使声明不受goto“?好吧,你仍然会遇到这样的情况:

goto later;
int size = 7;
int test[size];
later:

您实际上希望这做什么?

因此,禁止跳过 VLA 声明是有原因的 - 通过完全禁止它们来处理上述情况是最合乎逻辑的决定。

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

使用 goto 跳过变量声明? 的相关文章

随机推荐

  • Hive(查找连续 n 列中的最小值)

    我在 Hive 中有一个表 有 5 列 即电子邮件 a first date b first date c first date d first date a b c d 是用户可以执行的 4 个不同操作 上表中的 4 列表示用户执行第一个
  • 在 TFS 中以不同方式共享项目文档,您的最佳实践是什么? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我想知道在 TFS 2010 中管理 和版本控制 不同类型的项目文档 例如版本控制目标文档 例如 用例 主测试计划 质量保证计划和非版本控制相关
  • SQLAlchemy Pandas 从 jsonb 读取 sql

    我想用 pandas 生成一个数据框read sql https pandas pydata org pandas docs stable generated pandas read sql html来自我使用 PostgreSQL 进行的
  • 更改永久链接 WordPress 后出现 404 错误

    我的网站是一个Wordpress site创建于PHP 我已将永久链接默认更改为帖子名称 它工作得很好Chrome and Firefox但在 IE8 中不行 首页显示正确 但当我单击另一个页面的链接时 它显示 404 页面未找到错误 我使
  • Hibernate不生成级联

    我有一套hibernate hbm2ddl auto创建以便 Hibernate 为我在 mysql 中创建表 但是 休眠似乎没有正确添加Cascade关于表中的参考文献 然而 当我删除一行 并且我有一个删除级联作为休眠注释时 它确实有效
  • 强制 C++ 编译器检查异常处理

    我想知道是否有一些编译器参数 最好是在 gcc g 中 它将缺少 try catch 块视为错误 这是java中的标准行为 我一直很喜欢它 由于 Java 中的检查异常依赖于throw签名 您可以阅读为什么您不想使用throwC 中的函数签
  • MySQL 唯一 id 或组合 id

    我的项目和开发人员计划的结构如下 developer table id developer name etc project table id project name etc developer project table 因为一个开发人
  • php zlib:如何从字符串变量动态创建内存中的zip文件?

    这就是我需要的 a array folder gt anyfolder filename gt anyfilename filedata gt anyfiledata 我需要使用 a 中的压缩数据创建一个变量 zip 并将此 zip 输出到
  • Sass 更改监视间隔,更频繁地编译

    我正在使用 sass 将 scss 编译为 css 每次保存后 大约需要 15 20 秒才能编译为 scss 文件到 css 因此我需要刷新几次才能看到预期结果 有没有办法告诉 Sass 更频繁地检查更改 这是我使用的命令 sass wat
  • C# 中的随机数 [重复]

    这个问题在这里已经有答案了 可能的重复 随机数生成器没有按我计划的方式工作 C https stackoverflow com questions 767999 random number generator not working the
  • SharePoint 404 页面

    最好的位置是在 web config customError 部分中为 SharePoint 设置 404 错误页面 还是网站集 Web 应用程序上有配置设置 请阅读这个博客 http blogs msdn com jingmeili ar
  • 退出 glutFullScreen()

    我不明白为什么当我按 f 时它进入全屏但不退出全屏 在这个方法的开头我已经设置了bool fullscreen false 这是我的切换代码 case f toggle screenmode if fullscreen glutFullSc
  • 如何在 r 中绘制 LDA 的双标图?

    我使用该函数进行了线性判别分析lda 来自 MASS 包 现在我会尝试绘制像 ade4 包 forLDA 中那样的双标图 你知道我该怎么做吗 如果我尝试使用biplot 功能不起作用 例如 如果我使用 Iris 数据并制作 LDA dis2
  • 如何在 Scala Slick 中运行补丁/部分数据库更新?

    我们想运行补丁 部分UPDATE使用 Slick 3 0 0 以便我们只修改记录中的某些字段 确切地说哪些字段将被更新只有在运行时才知道 例如 对于一个REST PATCH request http restcookbook com HTT
  • C++11 中引入的可选固定宽度整数类型的支持状态

    C 11终于引入了固定宽度整数类型
  • 如果单元格为空白,如何停止公式?

    如果左侧单元格中没有数据 如何停止公式运行 我正在尝试弄清楚如何使用固定时间和动态时钟来显示经过的时间 我的固定时间在 Cell D5 中 动态时钟在 Cell 中J4 附图 为了计算出 经过的时间 我的公式如下 J4 D5 效果很好 但是
  • d3.js:是否可以通过键而不是索引来进行转换?

    我有不同长度的数据数组 x值 年 是有限年数的一部分 例如 var data Year 2008 Value 5 Year 2009 Value 6 or var data Year 2007 Value 8 Year 2009 Value
  • WordPress 操作钩子未触发(wpforms)

    最终完成了一个包含 WordPress 网站的项目 我正在尝试将 WPforms 制作的表单中的数据发布到外部 API 不是一个 WordPress 专家 但我读到我可以通过编写自己的插件来连接其他插件的操作 这是我的插件
  • Ember.js + Mirage:在集成测试中拉取模拟关系

    我有一个使用的组件this get model property 并且它按预期工作 对于我的集成测试 我使用 Mirage 它适用于我的所有其他测试 包括集成测试 但是当我测试这个特定组件时 我得到 TypeError Cannot rea
  • 使用 goto 跳过变量声明?

    我在读C 编程 现代方法由 K N King 学习 C 编程语言 并指出goto语句不得跳过可变长度数组声明 但现在的问题是 为什么goto跳转允许跳过 固定长度数组声明和普通声明吗 更准确地说 根据 C99 标准 此类示例的行为是什么 当