首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一个C++关于成员变量偏移地址的小Trick

一个C++关于成员变量偏移地址的小Trick

作者头像
owent
发布2018-08-01 17:06:51
发布2018-08-01 17:06:51
31400
代码可运行
举报
文章被收录于专栏:owentowent
运行总次数:0
代码可运行

今天看到一个小例子,发现了一个小trick。见代码:

代码语言:javascript
代码运行次数:0
运行
复制
#include <cstdio>
#include <cstdlib>

class base_1
{
public:
    int a;
};

class base_2
{
public:
    int b;
};

class base_3: public base_1, public base_2
{
public:
    int c;
};

int main(int argc, char* argv[]) {

    printf("&base_1::a = %p\n", &base_1::a);
    printf("&base_2::b = %p\n", &base_2::b);
    printf("&base_3::a = %p\n", &base_3::a);
    printf("&base_3::b = %p\n", &base_3::b);
    printf("&base_3::c = %p\n", &base_3::c);


    base_3 t;
    t.a = 1;
    t.b = 2;
    t.c = 3;

    typedef int (base_3::*tip);
    tip pm = NULL;

    printf("base_3::a = %d\n", t.base_3::a);
    printf("base_3::b = %d\n", t.base_3::b);
    printf("base_3::c = %d\n", t.base_3::c);

    pm = &base_3::a;
    printf("base_3::a(%p) = %d(ptr)\n", pm, t.*pm);
    pm = &base_3::b;
    printf("base_3::b(%p) = %d(ptr)\n", pm, t.*pm);
    pm = &base_3::c;
    printf("base_3::c(%p) = %d(ptr)\n", pm, t.*pm);

    return 0;
}

猜猜看这个代码输出什么? 答案是:

代码语言:javascript
代码运行次数:0
运行
复制
&base_1::a = 00000000
&base_2::b = 00000000
&base_3::a = 00000000
<u>&base_3::b = 00000000</u>
&base_3::c = 00000008
base_3::a = 1
base_3::b = 2
base_3::c = 3
base_3::a(00000000) = 1(ptr)
base_3::b(00000004) = 2(ptr)
base_3::c(00000008) = 3(ptr)

注意带下划线&base_3::b那一行,木有错,这个值不是4,而是0。我看了一下生成的汇编,很遗憾地他直接 push 0进栈了。 而下面赋值的pm = &base_3::b那里,汇编里直接 mov 了 4。 而且GCC和VC都是这样,所以不知道这么做的原因。

整理后记

原因:和编译优化有关。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2013-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 整理后记
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档