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

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

#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;
}

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

&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都是这样,所以不知道这么做的原因。

整理后记

原因:和编译优化有关。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏信安之路

CTF 玩转 pwn 月度总结

自从加入 RTIS 交流群, 在 7o8v 师傅, gd 大佬 的帮助下, PWN 学习之路进入加速度. 下面是 8 周学习的总结, 基本上是按照how2hea...

20200
来自专栏前端下午茶

Vue源码阅读 - 批量异步更新与nextTick原理

vue已是目前国内前端web端三分天下之一,同时也作为本人主要技术栈之一,在日常使用中知其然也好奇着所以然,另外最近的社区涌现了一大票vue源码阅读类的文章,在...

17830
来自专栏前端小作坊

原型链上的DOM Attributes

Chrome开发小组最近发表声明他们正在將DOM properties移动到原型链中。这个更新将会在Chrome 43(2015年4月发布beta版本)中实现。...

11630
来自专栏互联网开发者交流社区

JSP语法

19850
来自专栏知无涯

ASP跨站提交参数检测

369160
来自专栏赵俊的Java专栏

无限级菜单/权限树该如何设计

常用的树形显示插件有: JsTree, zTree, Layui Tree, Bootstrap Tree View 等。

75930
来自专栏Golang语言社区

GO语言高并发学习心得体会例

<div class="blockcode"><blockquote>信号 sigRecv1:=make(chan os.Signal,1) sigs1...

35980
来自专栏python3

beautiful soup爬虫初识

官方推荐使用lxml作为解析器,因为效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib, ...

14340
来自专栏前端下午茶

Vue源码阅读 - 依赖收集原理

vue已是目前国内前端web端三分天下之一,同时也作为本人主要技术栈之一,在日常使用中知其然也好奇着所以然,另外最近的社区涌现了一大票vue源码阅读类的文章,在...

25720
来自专栏ccylovehs

JavaScript异步编程

平时开发经常会用到js异步编程,由于前端展示页面都是基于网络机顶盒(IPTV的一般性能不太好,OTT较好),目前公司主要采取的异步编程的方式有setTimeou...

14820

扫码关注云+社区

领取腾讯云代金券