草庐IT

当我在 C 中打印一个未初始化的变量时会发生什么?

codeneng 2023-03-28 原文

What happens when I print an uninitialized variable in C++?

为什么会打印 32767 (或其他随机数)?什么是 std::cout 打印?为什么不是NULL(或0)?

int main() 
{
    int a;
    std::cout << a;
}

  • 为什么它不是 NULL(或 0)?因为标准没有说它必须初始化为 0。
  • 为什么人们只是喜欢看着枪管并扣动扳机并问"为什么我把头炸掉了?我拿起枪时不应该卸下Bullets吗"?
  • 您对术语"未实例化引用"的使用不正确。 int a 不是参考变量,它是一个普通的旧值变量。尽管我从未真正听过任何人谈论"实例化"原始类型(人们通常只在谈论用户定义的类时使用"实例化"这个词,即 classstruct 类型),当您定义一个值变量(这就是您对 int a 所做的)时,它肯定会被实例化。
  • @user3528438,来自 Java,它甚至不允许指针(尽管数组有点接近),这有点不同
  • @JosephNields,Java 中的引用与 C 中的指针非常相似。
  • @user3528438 在 Java 中,您只有用户定义类型的指针,除非他们称它们为"引用"。
  • 有趣的是,尽管我很确定之前有人问过这个问题,但我还没有找到 C 的问题。最Q
  • 这是未定义的行为。您正在打印占用 a 内存的任何内容,在这种情况下恰好是 32767.

    434511

    这是因为具有自动存储持续时间的变量在 C 中不会自动初始化为零。在 C 中,您不需要为不需要的东西付费,并且自动初始化变量需要时间(将内存位置设置为零最终会减少为机器指令,然后将其转换为控制物理位)。

    该变量被保留一个内存位置,并且碰巧在该内存位置有一些垃圾。 cout.

    正在打印该垃圾

    正如@dwcanillas 所指出的,这是未定义的行为。相关:C 中声明的、未初始化的变量会发生什么?它有价值吗?

    来自 C 标准(强调我的):

    8.5 初始化器 [dcl.init]

    7) To default-initialize an object of type T means:

    • If T is a (possibly cv-qualified) class type (Clause 9), constructors are
      considered. The applicable constructors are enumerated (13.3.1.3), and the best
      one for the initializer () is chosen through overload resolution (13.3). The
      constructor thus selected is called, with an empty argument list, to initialize >> the object.
    • If T is an array type, each element is default-initialized.
    • Otherwise, no initialization is performed.

    12) 如果没有为对象指定初始化器,则该对象是默认初始化的。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,如果没有对该对象执行初始化,则该对象将保留一个不确定的值,直到该值被替换(5.18)。 [注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。 — 尾注 ] 如果评估产生不确定的值,则行为未定义,但以下情况除外:

    — If an indeterminate value of unsigned narrow character type (3.9.1) is produced by the evaluation of:

    — the second or third operand of a conditional expression (5.16),

    — the right operand of a comma expression (5.19),

    — the operand of a cast or conversion to an unsigned narrow character type (4.7, 5.2.3, 5.2.9, 5.4), or

    — a discarded-value expression (Clause 5)

    ...

    434511

    C 14 (N3936) [dcl.init]/12 涵盖了该行为:

    If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced.

    [...] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

    并且您的代码未包含在任何"以下情况"中,这些情况涵盖了允许传播 unsigned char 不确定值的几种情况。

    434511

    因为 "a" 不是全局/静态的。它是一个自动变量,在运行时进行初始化。如果它是全局的,则初始化为零将在编译时发生。即

    ?静态变量在编译时初始化,因为它们的地址是已知且固定的。将它们初始化为 0 不会产生运行时成本。

    ?自动变量对于不同的调用可以有不同的地址,并且每次调用函数时都必须在运行时进行初始化,从而产生可能不需要的运行时成本。如果您确实需要该初始化,请请求它。

  • 这是未定义的行为。您正在打印占用 a 内存的任何内容,在这种情况下恰好是 32767.

    434511

    这是因为具有自动存储持续时间的变量在 C 中不会自动初始化为零。在 C 中,您不需要为不需要的东西付费,并且自动初始化变量需要时间(将内存位置设置为零最终会减少为机器指令,然后将其转换为控制物理位)。

    该变量被保留一个内存位置,并且碰巧在该内存位置有一些垃圾。 cout.

    正在打印该垃圾

    正如@dwcanillas 所指出的,这是未定义的行为。相关:C 中声明的、未初始化的变量会发生什么?它有价值吗?

    来自 C 标准(强调我的):

    8.5 初始化器 [dcl.init]

    7) To default-initialize an object of type T means:

    • If T is a (possibly cv-qualified) class type (Clause 9), constructors are
      considered. The applicable constructors are enumerated (13.3.1.3), and the best
      one for the initializer () is chosen through overload resolution (13.3). The
      constructor thus selected is called, with an empty argument list, to initialize >> the object.
    • If T is an array type, each element is default-initialized.
    • Otherwise, no initialization is performed.

    12) 如果没有为对象指定初始化器,则该对象是默认初始化的。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,如果没有对该对象执行初始化,则该对象将保留一个不确定的值,直到该值被替换(5.18)。 [注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。 — 尾注 ] 如果评估产生不确定的值,则行为未定义,但以下情况除外:

    — If an indeterminate value of unsigned narrow character type (3.9.1) is produced by the evaluation of:

    — the second or third operand of a conditional expression (5.16),

    — the right operand of a comma expression (5.19),

    — the operand of a cast or conversion to an unsigned narrow character type (4.7, 5.2.3, 5.2.9, 5.4), or

    — a discarded-value expression (Clause 5)

    ...

    434511

    C 14 (N3936) [dcl.init]/12 涵盖了该行为:

    If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced.

    [...] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

    并且您的代码未包含在任何"以下情况"中,这些情况涵盖了允许传播 unsigned char 不确定值的几种情况。

    434511

    因为 "a" 不是全局/静态的。它是一个自动变量,在运行时进行初始化。如果它是全局的,则初始化为零将在编译时发生。即

    ?静态变量在编译时初始化,因为它们的地址是已知且固定的。将它们初始化为 0 不会产生运行时成本。

    ?自动变量对于不同的调用可以有不同的地址,并且每次调用函数时都必须在运行时进行初始化,从而产生可能不需要的运行时成本。如果您确实需要该初始化,请请求它。

  • 这是未定义的行为。您正在打印占用 a 内存的任何内容,在这种情况下恰好是 32767.

    434511

    这是因为具有自动存储持续时间的变量在 C 中不会自动初始化为零。在 C 中,您不需要为不需要的东西付费,并且自动初始化变量需要时间(将内存位置设置为零最终会减少为机器指令,然后将其转换为控制物理位)。

    该变量被保留一个内存位置,并且碰巧在该内存位置有一些垃圾。 cout.

    正在打印该垃圾

    正如@dwcanillas 所指出的,这是未定义的行为。相关:C 中声明的、未初始化的变量会发生什么?它有价值吗?

    来自 C 标准(强调我的):

    8.5 初始化器 [dcl.init]

    7) To default-initialize an object of type T means:

    • If T is a (possibly cv-qualified) class type (Clause 9), constructors are
      considered. The applicable constructors are enumerated (13.3.1.3), and the best
      one for the initializer () is chosen through overload resolution (13.3). The
      constructor thus selected is called, with an empty argument list, to initialize >> the object.
    • If T is an array type, each element is default-initialized.
    • Otherwise, no initialization is performed.

    12) 如果没有为对象指定初始化器,则该对象是默认初始化的。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,如果没有对该对象执行初始化,则该对象将保留一个不确定的值,直到该值被替换(5.18)。 [注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。 — 尾注 ] 如果评估产生不确定的值,则行为未定义,但以下情况除外:

    — If an indeterminate value of unsigned narrow character type (3.9.1) is produced by the evaluation of:

    — the second or third operand of a conditional expression (5.16),

    — the right operand of a comma expression (5.19),

    — the operand of a cast or conversion to an unsigned narrow character type (4.7, 5.2.3, 5.2.9, 5.4), or

    — a discarded-value expression (Clause 5)

    ...

    434511

    C 14 (N3936) [dcl.init]/12 涵盖了该行为:

    If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced.

    [...] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

    并且您的代码未包含在任何"以下情况"中,这些情况涵盖了允许传播 unsigned char 不确定值的几种情况。

    434511

    因为 "a" 不是全局/静态的。它是一个自动变量,在运行时进行初始化。如果它是全局的,则初始化为零将在编译时发生。即

    ?静态变量在编译时初始化,因为它们的地址是已知且固定的。将它们初始化为 0 不会产生运行时成本。

    ?自动变量对于不同的调用可以有不同的地址,并且每次调用函数时都必须在运行时进行初始化,从而产生可能不需要的运行时成本。如果您确实需要该初始化,请请求它。


这是因为具有自动存储持续时间的变量在 C 中不会自动初始化为零。在 C 中,您不需要为不需要的东西付费,并且自动初始化变量需要时间(将内存位置设置为零最终会减少为机器指令,然后将其转换为控制物理位)。

该变量被保留一个内存位置,并且碰巧在该内存位置有一些垃圾。 cout.

正在打印该垃圾

正如@dwcanillas 所指出的,这是未定义的行为。相关:C 中声明的、未初始化的变量会发生什么?它有价值吗?

来自 C 标准(强调我的):

8.5 初始化器 [dcl.init]

7) To default-initialize an object of type T means:

  • If T is a (possibly cv-qualified) class type (Clause 9), constructors are
    considered. The applicable constructors are enumerated (13.3.1.3), and the best
    one for the initializer () is chosen through overload resolution (13.3). The
    constructor thus selected is called, with an empty argument list, to initialize >> the object.
  • If T is an array type, each element is default-initialized.
  • Otherwise, no initialization is performed.

12) 如果没有为对象指定初始化器,则该对象是默认初始化的。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,如果没有对该对象执行初始化,则该对象将保留一个不确定的值,直到该值被替换(5.18)。 [注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。 — 尾注 ] 如果评估产生不确定的值,则行为未定义,但以下情况除外:

— If an indeterminate value of unsigned narrow character type (3.9.1) is produced by the evaluation of:

— the second or third operand of a conditional expression (5.16),

— the right operand of a comma expression (5.19),

— the operand of a cast or conversion to an unsigned narrow character type (4.7, 5.2.3, 5.2.9, 5.4), or

— a discarded-value expression (Clause 5)

...

  • C 和 C 关于未初始化变量的规则有些不同。在 C 中,不确定的值可以在计算中传播。例如 int x; int y = x - 1; 在 C 中是合法的,并且导致 y 也是不确定的。但是,这会导致 C 中的 UB 。
  • @MattMcNabb 是的,我猜可能存在差异,正在热切地寻找骗子。但我最终找到了标准报价:)


这是未定义的行为。您正在打印占用 a 内存的任何内容,在这种情况下恰好是 32767.

  • @vsoftco stackoverflow.com/questions/11962457/… 公平地说,这不是我认为它是 UB 的原因 :)
  • 有趣...我会看一下帖子,谢谢!没错,就是UB,也相关stackoverflow.com/a/1597426/3093378, 1
  • 你的回答自相矛盾。您首先(正确地)声明程序具有未定义的行为,然后您描述"它做了什么",就好像它已经定义了行为一样。
  • @AsteroidsWithWings 我不同意。我的观点(至少在这个答案的上下文中)是"未定义的行为"是"不可预测的行为"。我并不是暗示他的代码总是会输出 32767。那只是他使用的例子,他甚至说行为不一致。我只是在问题的上下文中指出未定义行为的结果。
  • 没有"未定义行为的结果"。行为未定义。这就是它的意义所在。至少,对于在实践中可以合理预期的内容,这有点误导。
  • @AsteroidsWithWings 你错了。在这里,这篇文章比我能用 500 个字符更好地解释它:learncpp.com/cpp-tutorial/...
  • 那篇文章正是我所说的。不,我没有错。


C 14 (N3936) [dcl.init]/12 涵盖了该行为:

If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced.

[...] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

并且您的代码未包含在任何"以下情况"中,这些情况涵盖了允许传播 unsigned char 不确定值的几种情况。


因为 "a" 不是全局/静态的。它是一个自动变量,在运行时进行初始化。如果它是全局的,则初始化为零将在编译时发生。即

?静态变量在编译时初始化,因为它们的地址是已知且固定的。将它们初始化为 0 不会产生运行时成本。

?自动变量对于不同的调用可以有不同的地址,并且每次调用函数时都必须在运行时进行初始化,从而产生可能不需要的运行时成本。如果您确实需要该初始化,请请求它。

有关当我在 C 中打印一个未初始化的变量时会发生什么?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  7. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  8. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  9. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  10. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

随机推荐