C内存布局相关问题

查看:152
本文介绍了C内存布局相关问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

如下代码输出什么:

#include<stdio.h>
int main()
{
    char a=0;
    char b=0;
   
    int *p=(int *)&b;
    *p=258;
    printf("%d %d",a,b);
    return 0;
}

在看国外一本linux方面的书,里面讲到c语言内存布局相关,书中说这个程序运行结果是1 2,可是我再我的电脑(mac)上运行时02,并且想不明白这是为什么.
我目前仅有的思路如下:
258的二进制形式100000010
指针p指向了字符b的起始地址,字符与整形的地址对比可以通过下面的代码得出:

#include <stdio.h>
int main()
{
    char a = 0;
    char b = 0;
    char c = 0;
    int  d = 0;
    int  e = 0;
    int  f = 0;
    printf("%p\n",&a);
    printf("%p\n",&b);
    printf("%p\n",&c);
    printf("%p\n",&d);
    printf("%p\n",&e);
    printf("%p\n",&f);
    return 0;
}

代码输出
0x7fffc38df0df
0x7fffc38df0de
0x7fffc38df0dd
0x7fffc38df0d8
0x7fffc38df0d4
0x7fffc38df0d0
地址由高到低,所以我的理解是*p复制258(258的二进制形式100000010)会去覆盖字符a b 原有的值,所以b的值是00000010 a的值是000000001,a的值是1,b的值是2.此时涉及到大端与小端方式,我通过如下程序判断出我电脑环境为大端方式:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int hoge = 0x12345678;
    unsigned char *hoge_p =(unsigned char *)&hoge;
    printf("%x\n",hoge_p[0]);
    printf("%x\n",hoge_p[1]);
    printf("%x\n",hoge_p[2]);
    printf("%x\n",hoge_p[3]);
    
    return 0;
}

可是我实际运行中确实0 2.

解决方案

估计你开了编译器优化。

我的环境:

  • Ubuntu 16.04 (64 bit)

  • gcc 5.4.0

不开优化直接编译,结果的确是 1 2;但一旦开了优化(-O1, -O2, -O3, -Og结果都一样,其中 -Og 会报错),结果就变成了 0 2。原因在于:编译器在编译阶段就已经将值算好了,你输出的其实是常量。

-O1 优化的汇编代码举例(使用 gcc test.c -O1 -S 获得,这里只贴核心部分):

    movl    $2, %ecx
    movl    $0, %edx
    movl    $.LC0, %esi
    movl    $1, %edi
    movl    $0, %eax
    call    __printf_chk
    movl    $0, %eax

%edi, %esi, %edx, %ecx 分别是 __printf_chk 的参数,%esi 指向 %s %s 的地址。

可以发现最后两个参数并没有访问栈区,而是直接使用了立即数 0 和 2,可见这两个值的计算在编译期就已经完成了。

这篇关于C内存布局相关问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆