• Linux C下变量和常量的存储的本质


    源代码

    #cat main.c
    #include <stdio.h>
    
    int i = 100;
    
    int main(void)
    {
    	func();
    	return 0;
    }
    
    #cat func.c
    #include <stdio.h>
    
    extern i;
    
    int yyyy;
    char *s1 = "hello world
    ";
    
    int func()
    {
    	static int j = 200;
    	static int wwwww = 300;
    	printf("i:%d
    ",i);
    	printf("wwww:%d
    ",wwwww);
    	return 0;
    }
    
    gcc -o main func.c main.c
    

    变量的存储

    变量s1 存储在 .data里;

    #readelf -s main
        61: 0000000000601050     0 NOTYPE  GLOBAL DEFAULT   25 _end
        62: 0000000000400440     0 FUNC    GLOBAL DEFAULT   13 _start
        63: 0000000000601038     8 OBJECT  GLOBAL DEFAULT   24 s1
        64: 0000000000601034     4 OBJECT  GLOBAL DEFAULT   24 i
    
    #readelf -S main
      [23] .got.plt          PROGBITS         0000000000601000  00001000
           0000000000000030  0000000000000008  WA       0     0     8
      [24] .data             PROGBITS         0000000000601030  00001030
           0000000000000018  0000000000000000  WA       0     0     8
      [25] .bss              NOBITS           0000000000601048  00001048
    

    常量的存储

    hello world 存储在哪里? 我们知道是 rodata里,看看位置吧:

    #objdump -d -j .rodata main
    
    main:     file format elf64-x86-64
    
    
    Disassembly of section .rodata:
    
    0000000000400600 <_IO_stdin_used>:
      400600:	01 00 02 00 00 00 00 00                             ........
    
    0000000000400608 <__dso_handle>:
    	...
      400610:	68 65 6c 6c 6f 20 77 6f 72 6c 64 0a 00 69 3a 25     hello world..i:%
      400620:	64 0a 00 77 77 77 77 3a 25 64 0a 00                 d..wwww:%d..
    

    结合反汇编

    #objdump -D main > main.s
    

    这里看到s1的位置是601038 , 查看main.s

    #readelf -s main
        61: 0000000000601050     0 NOTYPE  GLOBAL DEFAULT   25 _end
        62: 0000000000400440     0 FUNC    GLOBAL DEFAULT   13 _start
        63: 0000000000601038     8 OBJECT  GLOBAL DEFAULT   24 s1
        64: 0000000000601034     4 OBJECT  GLOBAL DEFAULT   24 i
    
    #vim main.s
    0000000000601038 <s1>:
      601038:   10 06                   adc    %al,(%rsi)
      60103a:   40 00 00                add    %al,(%rax)
      60103d:   00 00                   add    %al,(%rax)
        ...
    

    const 全局变量

    const 可以将变量存储在哪里? - rodata

    这里,应该明白 const修饰后的变量,存储在rodata段,自然不能更改;

    指针本质

    #cat main.c
    #include <stdio.h>
    
    int i = 10;
    int *p = &i;
    
    int func(void)
    {
    	return 0;
    }
    
    int main(void)
    {
    	i = 20;
    	*p = 30;
    	return 0;
    }
    
    #gcc -o main  main.c
    

    汇编:

    #objdump -D main > main.s
    

    查看符号表:

    func函数的地址是:4004ed, 知道这个地址后,看汇编代码

    #readelf -s main
        54: 00000000004005a8     0 OBJECT  GLOBAL HIDDEN    15 __dso_handle
        55: 00000000004005a0     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
        56: 00000000004004ed    11 FUNC    GLOBAL DEFAULT   13 func
        57: 0000000000400520   101 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
        58: 0000000000601048     0 NOTYPE  GLOBAL DEFAULT   25 _end
        59: 0000000000400400     0 FUNC    GLOBAL DEFAULT   13 _start
    

    其实,看到汇编,可以明白,一个函数名,也是一个地址;

    #vim main.s
    00000000004004ed <func>:   // 函数名func 的地址是4004ed
      4004ed:   55                      push   %rbp
      4004ee:   48 89 e5                mov    %rsp,%rbp
      4004f1:   b8 00 00 00 00          mov    $0x0,%eax
      4004f6:   5d                      pop    %rbp
      4004f7:   c3                      retq
    
    00000000004004f8 <main>:
      4004f8:   55                      push   %rbp
      4004f9:   48 89 e5                mov    %rsp,%rbp
      4004fc:   c7 05 2a 0b 20 00 14    movl   $0x14,0x200b2a(%rip)        # 601030 <i>
      400503:   00 00 00
      400506:   48 8b 05 2b 0b 20 00    mov    0x200b2b(%rip),%rax        # 601038 <p>
      40050d:   c7 00 1e 00 00 00       movl   $0x1e,(%rax)
      400513:   b8 00 00 00 00          mov    $0x0,%eax
      400518:   5d                      pop    %rbp
      400519:   c3                      retq
      40051a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)```
  • 相关阅读:
    CentOS7 1 安装 ansible
    CentOS7 prometheus +node_exporter+Grafana 配置篇(原创)
    CentOS7 prometheus +node_exporter+Grafana 安装篇
    Oracle 查询重复记录 只保留一条 (转载)
    MySQL 查询重复数据(转载)
    Mongodb 查询重复数据(转载)
    Python报错:pymongo.errors.CursorNotFound: Cursor not found
    百万级高并发MongoDB集群性能数十倍提升优化实践(上篇)
    OPPO百万级高并发mongodb集群性能数十倍提升优化实践(下篇) 转载
    Oracle 常见等待事件及处理方法
  • 原文地址:https://www.cnblogs.com/muahao/p/10400229.html
Copyright © 2020-2023  润新知