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

关于 c 的一个问题不理解

  •  
  •   fvckDaybyte2 · 2019-07-29 11:10:22 +08:00 · 2784 次点击
    这是一个创建于 1938 天前的主题,其中的信息可能已经有所发展或是发生改变。
    环境:最新 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
    ShangShanXiaShan
        1
    ShangShanXiaShan  
       2019-07-29 11:34:03 +08:00
    未初始化的全局变量放在 bss
    wangyaominde
        2
    wangyaominde  
       2019-07-29 11:58:53 +08:00
    生成文件的大小难道不是生成的机器码的大小吗?
    BingoXuan
        3
    BingoXuan  
       2019-07-29 12:02:12 +08:00
    应该是编译器做了优化吧
    zealot0630
        4
    zealot0630  
       2019-07-29 12:06:26 +08:00   ❤️ 3
    objdump -t ./a.out 会告诉你答案
    wangyaominde
        5
    wangyaominde  
       2019-07-29 12:07:23 +08:00   ❤️ 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};的,之前遇到过编译器自作聪明删掉变量的。。。。猜测跟编译器相关。
    zealot0630
        6
    zealot0630  
       2019-07-29 12:07:28 +08:00   ❤️ 1
    配合 objdump -h 食用
    VDimos
        7
    VDimos  
       2019-07-29 12:11:13 +08:00 via Android
    文件大小和 has data ?
    iAcn
        8
    iAcn  
       2019-07-29 12:11:34 +08:00 via Android
    编译器把未使用的全局变量删了吧。
    menyakun
        9
    menyakun  
       2019-07-29 13:27:44 +08:00
    对于链接后的可执行文件来说,各个 section 之间是有很多 gap 的。你按数据大小来算文件大小,对比链接前的目标文件的话会更有可比性一点
    takeoffyoung
        10
    takeoffyoung  
       2019-07-29 13:32:12 +08:00   ❤️ 1
    代码编译之后可执行文件占用磁盘的大小和代码运行时占用内存的大小有啥关系呢。
    总不能说你的代码里面声明了一个占内存 10 个 G 的变量,你编译的可执行文件会占用 10 个 G 的磁盘空间?
    zyp0921
        11
    zyp0921  
       2019-07-29 13:41:09 +08:00   ❤️ 1
    可以去看看程序员的自我修养这本书。。。强力推荐哟
    johnkiller
        12
    johnkiller  
       2019-07-29 13:53:44 +08:00
    @takeoffyoung 正解
    kljsandjb
        13
    kljsandjb  
       2019-07-29 13:58:18 +08:00 via iPhone
    机器码啊,你比较一下,指令都是编码成二进制的
    johnkiller
        14
    johnkiller  
       2019-07-29 14:00:53 +08:00
    int a[100];

    int a[999];

    文件占用肯定都一样,

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

    个人理解,接受指正
    season4675
        15
    season4675  
       2019-07-29 14:05:32 +08:00
    你这是内存使用情况啊,和文件大小没关系啊……
    johnkiller
        16
    johnkiller  
       2019-07-29 14:06:14 +08:00
    1. malloc int, 100
    2. malloc flt, 999

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

    @takeoffyoung 只要对数组的一个成员进行初始化并且值不为 0,那么该数组将被放置在 data 段,data 段的内容会被写到可执行文件中。
    menyakun
        22
    menyakun  
       2019-07-29 15:08:36 +08:00
    @ShangShanXiaShan 对,是我理解岔了。bss 段只是一个对可执行文件大小的优化处理,bss 段和 data 段的变量在汇编代码生成的时候是一样的
    fvckDaybyte2
        23
    fvckDaybyte2  
    OP
       2019-07-30 18:23:54 +08:00
    @wangyaominde 请教下,这个是怎么弄出来的,是用楼上的 objdump 吗
    fvckDaybyte2
        24
    fvckDaybyte2  
    OP
       2019-07-30 18:26:35 +08:00
    @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

    看得不是很懂😂
    wangyaominde
        25
    wangyaominde  
       2019-07-31 10:25:39 +08:00   ❤️ 1
    @fvckDaybyte2 直接 gcc -S 生成.s 的汇编文件
    fvckDaybyte2
        26
    fvckDaybyte2  
    OP
       2019-07-31 10:41:26 +08:00 via iPhone
    @wangyaominde 谢谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5448 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 01:26 · PVG 09:26 · LAX 17:26 · JFK 20:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.