草庐IT

c++ - 正在阅读一个不是最近用 GCC 编写的未定义行为的成员吗?

coder 2024-02-01 原文

C++ reference 有以下用于 union 的 explanation,这个问题的有趣部分以粗体显示:

The union is only as big as necessary to hold its largest data member. The other data members are allocated in the same bytes as part of that largest member. The details of that allocation are implementation-defined, and it's undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement, as a non-standard language extension, the ability to read inactive members of a union.

现在,如果我在 Linux Mint 18 上使用 g++ -std=c++11 编译以下代码,我会得到以下输出(由 printf语句):

#include <cstdio>
using namespace std;

union myUnion {
    int var1; // 32 bits
    long int var2; // 64 bits
    char var3; // 8 bits
}; // union size is 64 bits (size of largest member)

int main()
{
    myUnion a;
    a.var1 = 10;
    printf("a is %ld bits and has value %d\n",sizeof(a)*8,a.var1); // ...has value 10
    a.var2 = 123456789;
    printf("a is %ld bits and has value %ld\n",sizeof(a)*8,a.var2); // ...has value 123456789
    a.var3 = 'y';
    printf("a is %ld bits and has value %c\n",sizeof(a)*8,a.var3); // ...has value y
    printf("a is %ld bits and has value %ld\n",sizeof(a)*8,a.var2); //... has value 123456789, why???
    return 0;
}

return 0 之前的行中,读取 a.var2 给出的不是 'y' 字符的 ASCII 小数(这是什么我预计,我是 union 的新手)但它最初定义的值(value)。根据 cppreference.com 的上述引用,我是否理解这是未定义的行为,因为它不是标准的,而是 GCC 的特定实现?

编辑

正如下面的出色答案所指出的,我在 return 0 之前的 printf 语句之后的注释中犯了一个复制错误。正确的版本是:

 printf("a is %ld bits and has value %ld\n",sizeof(a)*8,a.var2); //... has value 123456889, why???

即7 变为 8,因为前 8 位被 'y' 字符的 ASCII 值覆盖,即 121(0111 1001 二进制)。不过,我将保留它在上面代码中的原样,以与由此产生的精彩讨论保持一致。

最佳答案

未定义行为的有趣之处在于它与“随机”行为非常不同。编译器在处理未定义的行为时会有他们决定使用的行为,并且往往每次都表现出相同的行为。

恰当的例子:IDEOne 对这段代码有自己的解释:http://ideone.com/HO5id6

a is 32 bits and has value 10
a is 32 bits and has value 123456789
a is 32 bits and has value y
a is 32 bits and has value 123456889

您可能会注意到那里发生了一些有趣的事情(抛开 IDEOne 编译器的事实,long int 是 32 位而不是 64 位)。它仍将第 4 行显示为与第 2 行类似的读取方式,但该值实际上略有变化。似乎发生的事情是 'y'char 值是在 union 中设置的,但它没有改变任何其他位。当我将它切换为 long long int 而不是 long int 时,我得到了类似的行为。

您可能想检查,在您的示例中,第 4 行是否与之前的完全相同。我有点怀疑事实是否如此。

无论如何,为了回答您的具体问题,TL;DR 是在 GCC 中,写入 union 只会更改与您正在写入的特定成员关联的位,并且不能保证更改/清除 < em="">所有 其他位。当然,就像任何与 UB 相关的事物一样,不要假设任何其他编译器(甚至同一编译器的更高版本!)的行为相同。

关于c++ - 正在阅读一个不是最近用 GCC 编写的未定义行为的成员吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40113888/

有关c++ - 正在阅读一个不是最近用 GCC 编写的未定义行为的成员吗?的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

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

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

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

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

  4. 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=>

  5. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  8. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  9. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  10. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

随机推荐