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

Posted timer_go

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

00000000004004f8

:
4004f8: 55 push %rbp
4004f9: 48 89 e5 mov %rsp,%rbp
4004fc: c7 05 2a 0b 20 00 14 movl $0x14,0x200b2a(%rip) # 601030
400503: 00 00 00
400506: 48 8b 05 2b 0b 20 00 mov 0x200b2b(%rip),%rax # 601038


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)```











以上是关于Linux C下变量和常量的存储的本质的主要内容,如果未能解决你的问题,请参考以下文章

Linux下C程序的存储空间布局

Linux下C程序的存储空间布局

C语言源代码中怎样区分变量和常量

C语言 const常量讲解

C#本质论读书笔记

C变量常量