首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

关于 c 的一个问题不理解

  •  
  •   fvckDaybyte2 · 133 天前 · 1687 次点击
    这是一个创建于 133 天前的主题,其中的信息可能已经有所发展或是发生改变。
    环境:最新 mac os 以及自带的 gcc 环境
    如下代码中有一个全局变量 int a[30]
    '''
    #include <stdio.h>
    int a[30];
    int main() {
    printf("hello world");
    }
    '''
    如果吧 int a[30]; 注释掉,编译后可执行文件的大小是 8432byte ;
    如果不注释,可执行文件大小是 8456byte ;
    如果改成 int a[30]={1,2,3...30};,可执行文件大小依然是 8456byte ;
    已知 int 的在 mac 下大小是 4byte,int[30]的大小应该是 120byte,为何后两种情况可执行文件只增加了 24byte ? a 是记录在 data 段还是 bss 段?
    谢谢解答
    26 回复  |  直到 2019-07-31 10:41:26 +08:00
        1
    ShangShanXiaShan   133 天前
    未初始化的全局变量放在 bss
        2
    wangyaominde   133 天前
    生成文件的大小难道不是生成的机器码的大小吗?
        3
    BingoXuan   133 天前
    应该是编译器做了优化吧
        4
    zealot0630   133 天前   ♥ 3
    objdump -t ./a.out 会告诉你答案
        5
    wangyaominde   133 天前   ♥ 1
    https://i.loli.net/2019/07/29/5d3e6fc3702bc64628.png
    左侧是未注释的,汇编就差一句
    https://i.loli.net/2019/07/29/5d3e70930490b24948.png
    这个是 int a[30]={1,2,3...30};的,之前遇到过编译器自作聪明删掉变量的。。。。猜测跟编译器相关。
        6
    zealot0630   133 天前   ♥ 1
    配合 objdump -h 食用
        7
    VDimos   133 天前 via Android
    文件大小和 has data ?
        8
    iAcn   133 天前 via Android
    编译器把未使用的全局变量删了吧。
        9
    menyakun   133 天前
    对于链接后的可执行文件来说,各个 section 之间是有很多 gap 的。你按数据大小来算文件大小,对比链接前的目标文件的话会更有可比性一点
        10
    takeoffyoung   133 天前   ♥ 1
    代码编译之后可执行文件占用磁盘的大小和代码运行时占用内存的大小有啥关系呢。
    总不能说你的代码里面声明了一个占内存 10 个 G 的变量,你编译的可执行文件会占用 10 个 G 的磁盘空间?
        11
    zyp0921   133 天前   ♥ 1
    可以去看看程序员的自我修养这本书。。。强力推荐哟
        12
    johnkiller   133 天前
    @takeoffyoung 正解
        13
    kljsandjb   133 天前 via iPhone
    机器码啊,你比较一下,指令都是编码成二进制的
        14
    johnkiller   133 天前
    int a[100];

    int a[999];

    文件占用肯定都一样,

    我觉得文件的大小与生成的汇编语句量有关,而不是变量的大小啊,变量跟内存才有关

    个人理解,接受指正
        15
    season4675   133 天前
    你这是内存使用情况啊,和文件大小没关系啊……
        16
    johnkiller   133 天前
    1. malloc int, 100
    2. malloc flt, 999

    抽象描述大概应该就是这个意思,字符长度都一样,但是运行时内存占用不一样
        17
    menyakun   133 天前
    @takeoffyoung 如果你声明并初始化了一个占 10 个 G 的全局变量或这 static 变量的话,编译后的文件的确会占 10 多个 G
        18
    takeoffyoung   133 天前
    @menyakun 并不会,除非你的初始化是用相等长度的代码来实现的。这两者就是没有关系,如果在代码中用写下一千万个数字来初始化长度为一千万的数字。这种方式导致的可执行文件的大小的变化,并不能归纳到你的结论上。
        19
    Nitroethane   133 天前 via Android
    @ShangShanXiaShan 一楼正解
        20
    menyakun   133 天前
    @takeoffyoung 不是这个道理,就算再大的数组,只要有一个成员被初始化了,那么其他的文件就可以修改这个数组里的值,所以这个数组必须在链接时就被初始化,这样涉及到这个数组的汇编才能生成。重申一下,这里说的都是全局变量和局部静态变量。
        21
    ShangShanXiaShan   133 天前
    @menyakun 我没理解 “其他文件可以修改这个数组的值” 是什么意思。其他文件指的是其他源码文件?如果是,那么其他文件对这个数组的引用应该也是发生在运行时吧?这样子的话跟链接时是否初始化这个数组并没有多大的关系。

    @takeoffyoung 只要对数组的一个成员进行初始化并且值不为 0,那么该数组将被放置在 data 段,data 段的内容会被写到可执行文件中。
        22
    menyakun   133 天前
    @ShangShanXiaShan 对,是我理解岔了。bss 段只是一个对可执行文件大小的优化处理,bss 段和 data 段的变量在汇编代码生成的时候是一样的
        23
    fvckDaybyte2   132 天前
    @wangyaominde 请教下,这个是怎么弄出来的,是用楼上的 objdump 吗
        24
    fvckDaybyte2   132 天前
    @zealot0630 objdump -t data_bss_test_0

    data_bss_test_0: file format Mach-O 64-bit x86-64

    SYMBOL TABLE:
    0000000100000000 g F __TEXT,__text __mh_execute_header
    0000000100000f60 g F __TEXT,__text _main
    0000000000000000 *UND* _printf
    0000000000000000 *UND* dyld_stub_binder

    看得不是很懂😂
        25
    wangyaominde   131 天前   ♥ 1
    @fvckDaybyte2 直接 gcc -S 生成.s 的汇编文件
        26
    fvckDaybyte2   131 天前 via iPhone
    @wangyaominde 谢谢
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4301 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 28ms · UTC 01:41 · PVG 09:41 · LAX 17:41 · JFK 20:41
    ♥ Do have faith in what you're doing.