【知识科普】C语言的static究竟限制了谁

描述

【知识科普】C语言的static究竟限制了谁?

这是一个有趣的话题,虽然说教科书给了你一些说法,但你真正能把static说清楚吗?本文将通过一个案例,给大家做一个深度的拆解分析。 

注:在本文的讨论中,无明确说明时,指的都是static修饰函数,而非变量。

1 问题来源


最近的几个月一直在维护我的个人专属【嵌入式技术交流群】,平时大家都很积极在群里讨论技术问题。

就在上个星期,在群里收到一个有关static的讨论,我个人觉得挺有意思的,于是打算将其整理成文,希望能够帮助大家更好地理解和应用static这个关键字。

群里的原问题如下:

大佬们,问一个比较低智问题,static修饰的变量不是只能被当前文件所调用吗?为什么这里在其他.c文件可以调用get_board_led_opr这个函数获取board_demo_led_opr这个变量的值。

RT-Thread

2 关于上述问题的答疑


这个问题群里也给出了一些参考答案,而我一开始的回答,并没有直接回答答案,而是随手提出了3个问题:

问自己几个问题:

1.get函数返回什么地址(各种地址)语法上有约束条款吗?

2.static修饰的全局变量存放在哪里?它的地址是什么样的?

3.c语言里面要想访问任意一个地址,从语法层面上,能阻止得了吗?

提问者的回答:

(1)get_board_led_opr函数返回的是一个自定义的结构体get_board_led_opr。但是get_board_led_opr这个结构体被static修饰了。(2)get_board_led_opr结构体放在了board_demo.c中,而调用get_board_led_opr函数是在leddrv.c中。
(3)我询问了另外一个群里面的大佬,他们说,static仅仅在编译期间有用。在运行状态是无效果的。也就是说,虽然leddrv.c无法直接使用get_board_led_opr这个结构体。但是可以利用get_board_led_opr函数,间接的获取get_board_led_opr这个结构体,因为get_board_led_opr函数和et_board_led_opr这个结构体在同一个.c文件中
上述问题的点关键在于理解两个:
  • 被static修饰之后,这个变量变成了什么?
  • C语言的万能指针。
​​首先,被static修饰之后,意味着只有 当前的C语言C文件 可以直接 引用访问它,但是并不代表外部的模块(除当前C文件外的其他C文件)就不能访问它。直接访问肯定是不行的,但是 间接 的方式肯定是可以的。它的方法就是如上图的代码片段那样,将static变量的地址,以指针的形式传出去给其他模块即可。这里还要理解的一点是,被static修饰的变量是存放在全局的数据区,它的有效生存空间是整一个C工程运行时间内都是有效的。所以你通过指针去访问它,就变成了可能;这也是我们学习指针时,提到的 间接访问 的最真实体验。  

3 教科书里的static


乘此机会,我们来复习一下C语言教科书,对于static关键字,它们是怎么描述的?由于手头标准的教科书,已很难找了,索性问一下ChatGPT,看看它的总结:  

在C语言中,static关键字有两种主要的用法:静态变量和静态函数。

1. 静态变量:

静态变量是在程序运行期间一直存在的变量,其生命周期从声明处到程序结束。静态变量被存储在静态数据区,不会受到函数的调用和返回的影响,每次进入函数都会保留上一次的值。静态变量可以在函数内部或者全局作用域中声明。在函数内部声明的静态变量只能在该函数内部访问,而在全局作用域中声明的静态变量可以在整个文件中访问。静态变量的主要作用:- 维护变量的持久状态,保持值的连续性。- 限制变量的作用域,只能在函数内或者文件内访问。- 避免与同名的全局变量产生冲突。示例代码:

void func()

{

static int count = 0; // 定义一个静态变量

count++;

printf(“Count: %d ”, count);

}

int main()

{

func(); // 输出:Count: 1

func(); // 输出:Count: 2

func(); // 输出:Count: 3

return 0;

}

2. 静态函数:

静态函数是只能在当前源文件中使用的函数,其作用于只限于声明所在的文件,无法被其他文件调用。使用static关键字修饰函数,可以实现函数的隐藏和封装。因此,静态函数的主要作用是限制函数的作用域,防止其他文件访问该函数,避免命名冲突,并且提高代码的可读性和可维护性。示例代码:

static void util_func(int value)

{

printf(“Value: %d ”, value);

}

int main()

{

util_func(10); // 可以在当前文件中调用util_func函数

return 0;

}

总结:static关键字在C语言中的用法主要有静态变量和静态函数。静态变量用于维护变量的持久状态和限制作用域,静态函数用于限制函数的作用域和提高代码的可读性。

基本从ChatGPT的总结,可以了解清楚static的使用;不过它上面未提及到的一点是:

在static修饰的静态变量中,有两种情况,一种是修饰全局的变量,叫静态全局变量;另一种是修饰局部变量,叫静态局部变量(其实如果从作用周期的时间来看,它也是全局的)。ChatGPT中演示的静态局部变量,它的作用域就仅限于定义变量的这个函数内(准确说是,定义变量的大括号范围内);一旦出了这个作用域,是没有办法访问到的。而静态全局变量,它的作用域又比静态局部变量更宽泛些,它可以允许定义静态全局变量的整个C文件内,都可以访问它;但是之外的,其他C文件是无法访问的。综上,static关键字,主要强调的是 静态的 这个含义,无非就是作用域的大小问题。  4 C语言的static究竟限制了谁?
从编译原理和编译流程来拆解这个,问题的答案就很快就能出来。我们就以第3小节中,ChatGPT给出的示例代码为例,深度拆解一下这个static。在正式拆解之前,需要具备一些前置知识:C语言的编译流程。曾经,我写过一篇相关的文章,大家可以提前参考下,一文带你了解C代码到底是如何被编译的在这里,我不打算一一搬过来,仅仅把一张图贴过来参考:

RT-Thread

我们顺着这个思路来拆解跟踪一下代码里面的 static

  • 编写C代码(C源代码里面的static)


		

1main.c  2#include  3static int g_count = 0; 4void func()  5{ 6    static int l_count = 0// 定义一个静态局部变量        7    l_count++; 8    g_count++; 9    printf("l_count: %d, g_count: %d ", l_count, g_count);    10} 11static void util_func(int value) //定义一个静态函数 12{ 13    printf("Value: %d ", value); 14} 15extern void test_func(void); 16int main() 17{ 18    func();//输出:l_count:1 19    func();//输出:l_count:2 20    func();//输出:l_count:3 21    util_func(10);//可以在当前文件中调用util_func函数,输出:Value: 10 22    test_func(); // 调用test.c中的函数 23    return 0; 24}


		1test.c  2// 假设它们都是可以访问的  3extern int l_count;  4extern int g_count;  5extern void util_func(int value);  6void test_func(void)  7{  8#if 0  9    l_count++;  // 访问l_count静态局部变量,编译报错 10    g_count++;  // 访问g_count静态全局变量,编译报错 11    util_func(100); // 调用main.c中的static函数,编译报错 12#endif 13}

当test_func中的if-0打开后,根据我们上面的理论分析,肯定是编译不过的,如下:


		1test_static$ gcc -o test *.c 2/usr/bin/ld: /tmp/ccawkyDR.o: in function `test_func': 3test.c:(.text+0xa): undefined reference to `l_count' 4/usr/bin/ld: test.c:(.text+0x13): undefined reference to `l_count' 5/usr/bin/ld: test.c:(.text+0x19): undefined reference to `g_count' 6/usr/bin/ld: test.c:(.text+0x22): undefined reference to `g_count' 7/usr/bin/ld: test.c:(.text+0x2c): undefined reference to `util_func' 8collect2: error: ld returned 1 exit status

像这种就是很明显的找不到变量或函数的实现体,从而出现找不到引用的 链接 错误。

去掉这些引用后(if-0)打开,即可编译成功,且能够正常运行。


		

1test_static$ gcc -o test *.c 2test_static$ ./test 3l_count: 1, g_count: 1 4l_count: 2, g_count: 2 5l_count: 3, g_count: 3 6Value: 10

  • 分步拆解1:先看预处理后static的情况

使用的命令下:gcc -c -o main.o main.c -save-temps=obj

这时候我们可以看到 main.i main.s main.o 这几个文件。

先看main.i 的内容:


		1忽略前面对头文件内容的搬运  2873 "/usr/include/stdio.h" 3 4  32 "main.c" 2  43 "main.c"  5static int g_count = 0;  6void func()  7{  8 static int l_count = 0;  9 l_count++; 10 g_count++; 11 printf("l_count: %d, g_count: %d ", l_count, g_count); 12} 13static void util_func(int value) 14{ 15 printf("Value: %d ", value); 16} 17extern void test_func(void); 18int main() 19{ 20 func(); 21 func(); 22 func(); 23 util_func(10); 24 test_func(); 25 return 0;

从上基本可以看到,static还是在的,并且整一个预处理后的代码,基本保留了源代码的样子(原因是我们并没有使用类似宏定义的内容)。

  • 拆解第2步:看看汇编文件有没有static的影子

这时候我们要查看的是 main.s 文件:


		1test_static$ cat main.s  2        .file   "main.c"  3        .text  4        .local  g_count  5        .comm   g_count,4,4  6        .section        .rodata  7.LC0:  8        .string "l_count: %d, g_count: %d "  9        .text  10        .globl  func  11        .type   func, @function  12func:  13.LFB0:  14        .cfi_startproc  15        endbr64  16        pushq   %rbp  17        .cfi_def_cfa_offset 16  18        .cfi_offset 6, -16  19        movq    %rsp, %rbp  20        .cfi_def_cfa_register 6  21        movl    l_count.2316(%rip), %eax  22        addl    $1, %eax  23        movl    %eax, l_count.2316(%rip)  24        movl    g_count(%rip), %eax  25        addl    $1, %eax  26        movl    %eax, g_count(%rip)  27        movl    g_count(%rip), %edx  28        movl    l_count.2316(%rip), %eax  29        movl    %eax, %esi  30        leaq    .LC0(%rip), %rdi  31        movl    $0, %eax  32        call    printf@PLT  33        nop  34        popq    %rbp  35        .cfi_def_cfa 78  36        ret  37        .cfi_endproc  38.LFE0:  39        .size   func, .-func  40        .section        .rodata  41.LC1:  42        .string "Value: %d "  43        .text  44        .type   util_func, @function  45util_func:  46.LFB1:  47        .cfi_startproc  48        endbr64  49        pushq   %rbp  50        .cfi_def_cfa_offset 16  51        .cfi_offset 6, -16  52        movq    %rsp, %rbp  53        .cfi_def_cfa_register 6  54        subq    $16, %rsp  55        movl    %edi, -4(%rbp)  56        movl    -4(%rbp), %eax  57        movl    %eax, %esi  58        leaq    .LC1(%rip), %rdi  59        movl    $0, %eax  60        call    printf@PLT  61        nop  62        leave  63        .cfi_def_cfa 78  64        ret  65        .cfi_endproc  66.LFE1:  67        .size   util_func, .-util_func  68        .globl  main  69        .type   main, @function  70main:  71.LFB2:  72        .cfi_startproc  73        endbr64  74        pushq   %rbp  75        .cfi_def_cfa_offset 16  76        .cfi_offset 6, -16  77        movq    %rsp, %rbp  78        .cfi_def_cfa_register 6  79        movl    $0, %eax  80        call    func  81        movl    $0, %eax  82        call    func  83        movl    $0, %eax  84        call    func  85        movl    $10, %edi  86        call    util_func  87        call    test_func@PLT  88        movl    $0, %eax  89        popq    %rbp  90        .cfi_def_cfa 78  91        ret  92        .cfi_endproc  93.LFE2:  94        .size   main, .-main  95        .local  l_count.2316  96        .comm   l_count.2316,4,4  97        .ident  "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"  98        .section        .note.GNU-stack,"",@progbits  99        .section        .note.gnu.property,"a" 100        .align 8 101        .long    1f - 0f 102        .long    4f - 1f 103        .long    5 1040: 105        .string  "GNU" 1061: 107        .align 8 108        .long    0xc0000002 109        .long    3f - 2f 1102: 111        .long    0x3 1123: 113        .align 8 1144:

初一打开,可能有种不太认识的感觉,没关系,我们先找到我们能认识的东西。

先找到被static修饰过的内容(静态全局变量、静态局部变量、静态函数)。

1)静态全局变量g_count:


		

1        .file   "main.c" 2        .text 3        .local  g_count 4        .comm   g_count,4,4 5        .section        .rodata

2)静态局部变量l_count:


		1.LFE2: 2        .size   main.-main 3        .local  l_count.2316 4        .comm   l_count.2316,4,4

3)静态函数util_func:


		1        .string "Value: %d "  2        .text  3        .type   util_func, @function  4util_func:  5.LFB1:  6        .cfi_startproc  7        endbr64  8        pushq   %rbp  9        .cfi_def_cfa_offset 16 10        .cfi_offset 6, -16 11        movq    %rsp, %rbp 12        .cfi_def_cfa_register 6 13        subq    $16, %rsp 14        movl    %edi, -4(%rbp) 15        movl    -4(%rbp), %eax 16        movl    %eax, %esi 17        leaq    .LC1(%rip), %rdi 18        movl    $0, %eax 19        call    printf@PLT 20        nop 21        leave 22        .cfi_def_cfa 78 23        ret 24        .cfi_endproc

由于我们只是对main.c进行汇编,所以看不出全貌,但是能够确认的是,在汇编文件中,static已经消失了,换句话说,接下来就没static啥事情了,而是转为其他信息了。我们接着往下拆解。

  • 拆解第3步:obj文件里面确认没有static的要素吗?

我们看下main.o文件,由于它不是可读文件,所以得用其他指令分析下:


		

1test_static$ readelf -a main.o 2ELF Header: 3  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  4  Class:                             ELF64 5  Data:                              2's complement, little endian 6  Version:                           1 (current) 7  OS/ABI:                            UNIX - System V 8  ABI Version:                       0 9  Type:                              REL (Relocatable file) 10  Machine:                           Advanced Micro Devices X86-64 11  Version:                           0x1 12  Entry point address:               0x0 13  Start of program headers:          0 (bytes into file) 14  Start of section headers:          1520 (bytes into file) 15  Flags:                             0x0 16  Size of this header:               64 (bytes) 17  Size of program headers:           0 (bytes) 18  Number of program headers:         0 19  Size of section headers:           64 (bytes) 20  Number of section headers:         14 21  Section header string table index13 22Section Headers: 23  [Nr] Name              Type             Address           Offset 24       Size              EntSize          Flags  Link  Info  Align 25  [ 0]                   NULL             0000000000000000  00000000 26       0000000000000000  0000000000000000           0     0     0 27  [ 1] .text             PROGBITS         0000000000000000  00000040 28       00000000000000ac  0000000000000000  AX       0     0     1 29  [ 2] .rela.text        RELA             0000000000000000  000003e0 30       0000000000000150  0000000000000018   I      11     1     8 31  [ 3] .data             PROGBITS         0000000000000000  000000ec 32       0000000000000000  0000000000000000  WA       0     0     1 33  [ 4] .bss              NOBITS           0000000000000000  000000ec 34       0000000000000008  0000000000000000  WA       0     0     4 35  [ 5] .rodata           PROGBITS         0000000000000000  000000ec 36       0000000000000025  0000000000000000   A       0     0     1 37  [ 6] .comment          PROGBITS         0000000000000000  00000111 38       000000000000002c  0000000000000001  MS       0     0     1 39  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  0000013d 40       0000000000000000  0000000000000000           0     0     1 41  [ 8] .note.gnu.propert NOTE             0000000000000000  00000140 42       0000000000000020  0000000000000000   A       0     0     8 43  [ 9] .eh_frame         PROGBITS         0000000000000000  00000160 44       0000000000000078  0000000000000000   A       0     0     8 45  [10] .rela.eh_frame    RELA             0000000000000000  00000530 46       0000000000000048  0000000000000018   I      11     9     8 47  [11] .symtab           SYMTAB           0000000000000000  000001d8 48       00000000000001b0  0000000000000018          12    13     8 49  [12] .strtab           STRTAB           0000000000000000  00000388 50       0000000000000053  0000000000000000           0     0     1 51  [13] .shstrtab         STRTAB           0000000000000000  00000578 52       0000000000000074  0000000000000000           0     0     1 53Key to Flags: 54  W (write), A (alloc), X (execute), M (merge), S (strings), I (info), 55  L (link order), O (extra OS processing required), G (group), T (TLS), 56  C (compressed), x (unknown), o (OS specific), E (exclude), 57  l (large), p (processor specific) 58There are no section groups in this file. 59There are no program headers in this file. 60There is no dynamic section in this file. 61Relocation section '.rela.text' at offset 0x3e0 contains 14 entries: 62  Offset          Info           Type           Sym. Value    Sym. Name + Addend 6300000000000a  000400000002 R_X86_64_PC32     0000000000000000 .bss + 0 64000000000013  000400000002 R_X86_64_PC32     0000000000000000 .bss + 0 65000000000019  000400000002 R_X86_64_PC32     0000000000000000 .bss - 4 66000000000022  000400000002 R_X86_64_PC32     0000000000000000 .bss - 4 67000000000028  000400000002 R_X86_64_PC32     0000000000000000 .bss - 4 6800000000002e  000400000002 R_X86_64_PC32     0000000000000000 .bss + 0 69000000000037  000600000002 R_X86_64_PC32     0000000000000000 .rodata - 4 70000000000041  000f00000004 R_X86_64_PLT32    0000000000000000 printf - 4 7100000000005f  000600000002 R_X86_64_PC32     0000000000000000 .rodata + 16 72000000000069  000f00000004 R_X86_64_PLT32    0000000000000000 printf - 4 7300000000007e  000d00000004 R_X86_64_PLT32    0000000000000000 func - 4 74000000000088  000d00000004 R_X86_64_PLT32    0000000000000000 func - 4 75000000000092  000d00000004 R_X86_64_PLT32    0000000000000000 func - 4 760000000000a1  001100000004 R_X86_64_PLT32    0000000000000000 test_func - 4 77Relocation section '.rela.eh_frame' at offset 0x530 contains 3 entries: 78  Offset          Info           Type           Sym. Value    Sym. Name + Addend 79000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0 80000000000040  000200000002 R_X86_64_PC32     0000000000000000 .text + 48 81000000000060  000200000002 R_X86_64_PC32     0000000000000000 .text + 70 82The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. 83Symbol table '.symtab' contains 18 entries: 84   Num:    Value          Size Type    Bind   Vis      Ndx Name 85     00000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND  86     10000000000000000     0 FILE    LOCAL  DEFAULT  ABS main.c 87     20000000000000000     0 SECTION LOCAL  DEFAULT    1  88     30000000000000000     0 SECTION LOCAL  DEFAULT    3  89     40000000000000000     0 SECTION LOCAL  DEFAULT    4  90     50000000000000000     4 OBJECT  LOCAL  DEFAULT    4 g_count 91     60000000000000000     0 SECTION LOCAL  DEFAULT    5  92     70000000000000004     4 OBJECT  LOCAL  DEFAULT    4 l_count.2316 93     80000000000000048    40 FUNC    LOCAL  DEFAULT    1 util_func 94     90000000000000000     0 SECTION LOCAL  DEFAULT    7  95    100000000000000000     0 SECTION LOCAL  DEFAULT    8  96    110000000000000000     0 SECTION LOCAL  DEFAULT    9  97    120000000000000000     0 SECTION LOCAL  DEFAULT    6  98    130000000000000000    72 FUNC    GLOBAL DEFAULT    1 func 99    140000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_ 100    150000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND printf 101    160000000000000070    60 FUNC    GLOBAL DEFAULT    1 main 102    170000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND test_func 103No version information found in this file. 104Displaying notes found in: .note.gnu.property 105  Owner                Data size        Description 106  GNU                  0x00000010       NT_GNU_PROPERTY_TYPE_0 107      Properties: x86 feature: IBT, SHSTK 108recan@ubuntu:~/win_share_workspace/test_share/test_static$

从上面可以看到,g_count、l_count、util_func 都被 LOCAL 修饰了,而非 GLOBAL 的:

		1     50000000000000000     4 OBJECT  LOCAL  DEFAULT    4 g_count 2     60000000000000000     0 SECTION LOCAL  DEFAULT    5  3     70000000000000004     4 OBJECT  LOCAL  DEFAULT    4 l_count.2316 4     80000000000000048    40 FUNC    LOCAL  DEFAULT    1 util_func 

究竟这两者修饰有啥区别,会产生什么影响呢?我们接着往下拆解。

  • 拆解第4步:链接后的可执行文件反汇编

前面也说到了,由于我们都只看到 main这个C文件相关 预处理、汇编、obj内容,而没有看到整个可执行文件的全貌。

执行反汇编看看:


		1test_static$ objdump -l -d -x -s -S test  2test:     file format elf64-x86-64  3test  4architecture: i386:x86-64, flags 0x00000150:  5HAS_SYMS, DYNAMIC, D_PAGED  6start address 0x0000000000001060  7Program Header:  8    PHDR off    0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3  9         filesz 0x00000000000002d8 memsz 0x00000000000002d8 flags r--  10  INTERP off    0x0000000000000318 vaddr 0x0000000000000318 paddr 0x0000000000000318 align 2**0  11         filesz 0x000000000000001c memsz 0x000000000000001c flags r--  12    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**12  13         filesz 0x0000000000000600 memsz 0x0000000000000600 flags r--  14    LOAD off    0x0000000000001000 vaddr 0x0000000000001000 paddr 0x0000000000001000 align 2**12  15         filesz 0x0000000000000285 memsz 0x0000000000000285 flags r-x  16    LOAD off    0x0000000000002000 vaddr 0x0000000000002000 paddr 0x0000000000002000 align 2**12  17         filesz 0x00000000000001f0 memsz 0x00000000000001f0 flags r--  18    LOAD off    0x0000000000002db8 vaddr 0x0000000000003db8 paddr 0x0000000000003db8 align 2**12  19         filesz 0x0000000000000258 memsz 0x0000000000000268 flags rw-  20 DYNAMIC off    0x0000000000002dc8 vaddr 0x0000000000003dc8 paddr 0x0000000000003dc8 align 2**3  21         filesz 0x00000000000001f0 memsz 0x00000000000001f0 flags rw-  22    NOTE off    0x0000000000000338 vaddr 0x0000000000000338 paddr 0x0000000000000338 align 2**3  23         filesz 0x0000000000000020 memsz 0x0000000000000020 flags r--  24    NOTE off    0x0000000000000358 vaddr 0x0000000000000358 paddr 0x0000000000000358 align 2**2  25         filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--  260x6474e553 off    0x0000000000000338 vaddr 0x0000000000000338 paddr 0x0000000000000338 align 2**3  27         filesz 0x0000000000000020 memsz 0x0000000000000020 flags r--  28EH_FRAME off    0x000000000000202c vaddr 0x000000000000202c paddr 0x000000000000202c align 2**2  29         filesz 0x000000000000005c memsz 0x000000000000005c flags r--  30   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4  31         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-  32   RELRO off    0x0000000000002db8 vaddr 0x0000000000003db8 paddr 0x0000000000003db8 align 2**0  33         filesz 0x0000000000000248 memsz 0x0000000000000248 flags r--  34Dynamic Section:  35  NEEDED               libc.so.6  36  INIT                 0x0000000000001000  37  FINI                 0x0000000000001278  38  INIT_ARRAY           0x0000000000003db8  39  INIT_ARRAYSZ         0x0000000000000008  40  FINI_ARRAY           0x0000000000003dc0  41  FINI_ARRAYSZ         0x0000000000000008  42  GNU_HASH             0x00000000000003a0  43  STRTAB               0x0000000000000470  44  SYMTAB               0x00000000000003c8  45  STRSZ                0x0000000000000084  46  SYMENT               0x0000000000000018  47  DEBUG                0x0000000000000000  48  PLTGOT               0x0000000000003fb8  49  PLTRELSZ             0x0000000000000018  50  PLTREL               0x0000000000000007  51  JMPREL               0x00000000000005e8  52  RELA                 0x0000000000000528  53  RELASZ               0x00000000000000c0  54  RELAENT              0x0000000000000018  55  FLAGS                0x0000000000000008  56  FLAGS_1              0x0000000008000001  57  VERNEED              0x0000000000000508  58  VERNEEDNUM           0x0000000000000001  59  VERSYM               0x00000000000004f4  60  RELACOUNT            0x0000000000000003  61Version References:  62  required from libc.so.6:  63    0x09691a75 0x00 02 GLIBC_2.2.5  64Sections:  65Idx Name          Size      VMA               LMA               File off  Algn  66  0 .interp       0000001c  0000000000000318  0000000000000318  00000318  2**0  67                  CONTENTS, ALLOC, LOAD, READONLY, DATA  68  1 .note.gnu.property 00000020  0000000000000338  0000000000000338  00000338  2**3  69                  CONTENTS, ALLOC, LOAD, READONLY, DATA  70  2 .note.gnu.build-id 00000024  0000000000000358  0000000000000358  00000358  2**2  71                  CONTENTS, ALLOC, LOAD, READONLY, DATA  72  3 .note.ABI-tag 00000020  000000000000037c  000000000000037c  0000037c  2**2  73                  CONTENTS, ALLOC, LOAD, READONLY, DATA  74  4 .gnu.hash     00000024  00000000000003a0  00000000000003a0  000003a0  2**3  75                  CONTENTS, ALLOC, LOAD, READONLY, DATA  76  5 .dynsym       000000a8  00000000000003c8  00000000000003c8  000003c8  2**3  77                  CONTENTS, ALLOC, LOAD, READONLY, DATA  78  6 .dynstr       00000084  0000000000000470  0000000000000470  00000470  2**0  79                  CONTENTS, ALLOC, LOAD, READONLY, DATA  80  7 .gnu.version  0000000e  00000000000004f4  00000000000004f4  000004f4  2**1  81                  CONTENTS, ALLOC, LOAD, READONLY, DATA  82  8 .gnu.version_r 00000020  0000000000000508  0000000000000508  00000508  2**3  83                  CONTENTS, ALLOC, LOAD, READONLY, DATA  84  9 .rela.dyn     000000c0  0000000000000528  0000000000000528  00000528  2**3  85                  CONTENTS, ALLOC, LOAD, READONLY, DATA  86 10 .rela.plt     00000018  00000000000005e8  00000000000005e8  000005e8  2**3  87                  CONTENTS, ALLOC, LOAD, READONLY, DATA  88 11 .init         0000001b  0000000000001000  0000000000001000  00001000  2**2  89                  CONTENTS, ALLOC, LOAD, READONLY, CODE  90 12 .plt          00000020  0000000000001020  0000000000001020  00001020  2**4  91                  CONTENTS, ALLOC, LOAD, READONLY, CODE  92 13 .plt.got      00000010  0000000000001040  0000000000001040  00001040  2**4  93                  CONTENTS, ALLOC, LOAD, READONLY, CODE  94 14 .plt.sec      00000010  0000000000001050  0000000000001050  00001050  2**4  95                  CONTENTS, ALLOC, LOAD, READONLY, CODE  96 15 .text         00000215  0000000000001060  0000000000001060  00001060  2**4  97                  CONTENTS, ALLOC, LOAD, READONLY, CODE  98 16 .fini         0000000d  0000000000001278  0000000000001278  00001278  2**2  99                  CONTENTS, ALLOC, LOAD, READONLY, CODE 100 17 .rodata       00000029  0000000000002000  0000000000002000  00002000  2**2 101                  CONTENTS, ALLOC, LOAD, READONLY, DATA 102 18 .eh_frame_hdr 0000005c  000000000000202c  000000000000202c  0000202c  2**2 103                  CONTENTS, ALLOC, LOAD, READONLY, DATA 104 19 .eh_frame     00000168  0000000000002088  0000000000002088  00002088  2**3 105                  CONTENTS, ALLOC, LOAD, READONLY, DATA 106 20 .init_array   00000008  0000000000003db8  0000000000003db8  00002db8  2**3 107                  CONTENTS, ALLOC, LOADDATA 108 21 .fini_array   00000008  0000000000003dc0  0000000000003dc0  00002dc0  2**3 109                  CONTENTS, ALLOC, LOADDATA 110 22 .dynamic      000001f0  0000000000003dc8  0000000000003dc8  00002dc8  2**3 111                  CONTENTS, ALLOC, LOADDATA 112 23 .got          00000048  0000000000003fb8  0000000000003fb8  00002fb8  2**3 113                  CONTENTS, ALLOC, LOADDATA 114 24 .data         00000010  0000000000004000  0000000000004000  00003000  2**3 115                  CONTENTS, ALLOC, LOADDATA 116 25 .bss          00000010  0000000000004010  0000000000004010  00003010  2**2 117                  ALLOC 118 26 .comment      0000002b  0000000000000000  0000000000000000  00003010  2**0 119                  CONTENTS, READONLY 120SYMBOL TABLE: 1210000000000000318 l    d  .interp        0000000000000000              .interp 1220000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property 1230000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id 124000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag 12500000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash 12600000000000003c8 l    d  .dynsym        0000000000000000              .dynsym 1270000000000000470 l    d  .dynstr        0000000000000000              .dynstr 12800000000000004f4 l    d  .gnu.version   0000000000000000              .gnu.version 1290000000000000508 l    d  .gnu.version_r 0000000000000000              .gnu.version_r 1300000000000000528 l    d  .rela.dyn      0000000000000000              .rela.dyn 13100000000000005e8 l    d  .rela.plt      0000000000000000              .rela.plt 1320000000000001000 l    d  .init  0000000000000000              .init 1330000000000001020 l    d  .plt   0000000000000000              .plt 1340000000000001040 l    d  .plt.got       0000000000000000              .plt.got 1350000000000001050 l    d  .plt.sec       0000000000000000              .plt.sec 1360000000000001060 l    d  .text  0000000000000000              .text 1370000000000001278 l    d  .fini  0000000000000000              .fini 1380000000000002000 l    d  .rodata        0000000000000000              .rodata 139000000000000202c l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr 1400000000000002088 l    d  .eh_frame      0000000000000000              .eh_frame 1410000000000003db8 l    d  .init_array    0000000000000000              .init_array 1420000000000003dc0 l    d  .fini_array    0000000000000000              .fini_array 1430000000000003dc8 l    d  .dynamic       0000000000000000              .dynamic 1440000000000003fb8 l    d  .got   0000000000000000              .got 1450000000000004000 l    d  .data  0000000000000000              .data 1460000000000004010 l    d  .bss   0000000000000000              .bss 1470000000000000000 l    d  .comment       0000000000000000              .comment 1480000000000000000 l    df *ABS*  0000000000000000              crtstuff.c 1490000000000001090 l     F .text  0000000000000000              deregister_tm_clones 15000000000000010c0 l     F .text  0000000000000000              register_tm_clones 1510000000000001100 l     F .text  0000000000000000              __do_global_dtors_aux 1520000000000004010 l     O .bss   0000000000000001              completed.8061 1530000000000003dc0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry 1540000000000001140 l     F .text  0000000000000000              frame_dummy 1550000000000003db8 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry 1560000000000000000 l    df *ABS*  0000000000000000              main.c 1570000000000004014 l     O .bss   0000000000000004              g_count 1580000000000004018 l     O .bss   0000000000000004              l_count.2316 1590000000000001191 l     F .text  0000000000000028              util_func 1600000000000000000 l    df *ABS*  0000000000000000              test.c 1610000000000000000 l    df *ABS*  0000000000000000              crtstuff.c 16200000000000021ec l     O .eh_frame      0000000000000000              __FRAME_END__ 1630000000000000000 l    df *ABS*  0000000000000000               1640000000000003dc0 l       .init_array    0000000000000000              __init_array_end 1650000000000003dc8 l     O .dynamic       0000000000000000              _DYNAMIC 1660000000000003db8 l       .init_array    0000000000000000              __init_array_start 167000000000000202c l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR 1680000000000003fb8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_ 1690000000000001000 l     F .init  0000000000000000              _init 1700000000000001270 g     F .text  0000000000000005              __libc_csu_fini 1710000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable 1720000000000004000  w      .data  0000000000000000              data_start 1730000000000004010 g       .data  0000000000000000              _edata 1740000000000001278 g     F .fini  0000000000000000              .hidden _fini 1750000000000000000       F *UND*  0000000000000000              printf@@GLIBC_2.2.5 17600000000000011f5 g     F .text  000000000000000b              test_func 1770000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5 1780000000000004000 g       .data  0000000000000000              __data_start 1790000000000000000  w      *UND*  0000000000000000              __gmon_start__ 1800000000000004008 g     O .data  0000000000000000              .hidden __dso_handle 1810000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used 1820000000000001149 g     F .text  0000000000000048              func 1830000000000001200 g     F .text  0000000000000065              __libc_csu_init 1840000000000004020 g       .bss   0000000000000000              _end 1850000000000001060 g     F .text  000000000000002f              _start 1860000000000004010 g       .bss   0000000000000000              __bss_start 18700000000000011b9 g     F .text  000000000000003c              main 1880000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__ 1890000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable 1900000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5 191Contents of section .interp: 192 0318 2f6c6962 36342f6c 642d6c69 6e75782d  /lib64/ld-linux- 193 0328 783836236342e73 6f2e3200           x86-64.so.2.     194     省略了一些无关紧要的内容 195Contents of section .data: 196 4000 00000000 00000000 08400000 00000000  .........@...... 197Contents of section .comment: 198 0000 474343320285562 756e7475 20392e34  GCC: (Ubuntu 9.4 199 0010 2e302d31 7562756747531732302e30  .0-1ubuntu1~20.0 200 0020 342e3129 20392e34 2e3000             4.19.4.0.      201Disassembly of section .init: 2020000000000001000 <_init>: 203_init(): 204    1000:       f3 01e fa             endbr64  205    1004:       48 83 ec 08             sub    $0x8,%rsp 206    1008:       48 805 d9 200 00    mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__> 207    100f:       48 85 c0                test   %rax,%rax 208    1012:       74 02                   je     1016 <_init+0x16> 209    1014:       ff d0                   callq  *%rax 210    1016:       48 83 c4 08             add    $0x8,%rsp 211    101a:       c3                      retq    212Disassembly of section .plt: 2130000000000001020 <.plt>: 214    1020:       ff 35 9200 00       pushq  0x2f9a(%rip)        # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x8> 215    1026:       f2 ff 25 9200 00    bnd jmpq *0x2f9b(%rip)        # 3fc8 <_GLOBAL_OFFSET_TABLE_+0x10> 216    102d:       0100                nopl   (%rax) 217    1030:       f3 01e fa             endbr64  218    1034:       68 00 00 00 00          pushq  $0x0 219    1039:       f2 e9 e1 ff ff ff       bnd jmpq 1020 <.plt> 220    103f:       90                      nop 221Disassembly of section .plt.got: 2220000000000001040 <__cxa_finalize@plt>: 223    1040:       f3 01e fa             endbr64  224    1044:       f2 ff 25 ad 200 00    bnd jmpq *0x2fad(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 225    104b:       0144 00 00          nopl   0x0(%rax,%rax,1) 226Disassembly of section .plt.sec: 2270000000000001050 : 228    1050:       f3 01e fa             endbr64  229    1054:       f2 ff 25 75 200 00    bnd jmpq *0x2f75(%rip)        # 3fd0 @glibc_2.2.5> 230    105b:       0144 00 00          nopl   0x0(%rax,%rax,1) 231Disassembly of section .text: 2320000000000001060 <_start>: 233_start(): 234    1060:       f3 01e fa             endbr64  235    1064:       31 ed                   xor    %ebp,%ebp 236    1066:       49 89 d1                mov    %rdx,%r9 237    1069:       5e                      pop    %rsi 238    106a:       48 89 e2                mov    %rsp,%rdx 239    106d:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp 240    1071:       50                      push   %rax 241    1072:       54                      push   %rsp 242    1073:       4805 f6 01 00 00    lea    0x1f6(%rip),%r8        # 1270 <__libc_csu_fini> 243    107a:       48 80701 00 00    lea    0x17f(%rip),%rcx        # 1200 <__libc_csu_init> 244    1081:       48 8331 01 00 00    lea    0x131(%rip),%rdi        # 11b9 245    1088:       ff 15 52 200 00       callq  *0x2f52(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.2.5> 246    108e:       f4                      hlt     247    108f:       90                      nop 2480000000000001090 : 249deregister_tm_clones(): 250    1090:       48 8379 200 00    lea    0x2f79(%rip),%rdi        # 4010 <__TMC_END__> 251    1097:       48 805 72 200 00    lea    0x2f72(%rip),%rax        # 4010 <__TMC_END__> 252    109e:       48 39 f8                cmp    %rdi,%rax 253    10a1:       74 15                   je     10b8 0x28> 254    10a3:       48 805 2200 00    mov    0x2f2e(%rip),%rax        # 3fd8 <_ITM_deregisterTMCloneTable> 255    10aa:       48 85 c0                test   %rax,%rax 256    10ad:       74 09                   je     10b8 0x28> 257    10af:       ff e0                   jmpq   *%rax 258    10b1:       0180 00 00 00 00    nopl   0x0(%rax) 259    10b8:       c3                      retq    260    10b9:       0180 00 00 00 00    nopl   0x0(%rax) 26100000000000010c0 : 262register_tm_clones(): 263    10c0:       48 8349 200 00    lea    0x2f49(%rip),%rdi        # 4010 <__TMC_END__> 264    10c7:       48 835 42 200 00    lea    0x2f42(%rip),%rsi        # 4010 <__TMC_END__> 265    10ce:       48 29 fe                sub    %rdi,%rsi 266    10d1:       48 89 f0                mov    %rsi,%rax 267    10d4:       48 c1 ee 3f             shr    $0x3f,%rsi 268    10d8:       48 c1 f8 03             sar    $0x3,%rax 269    10dc:       48 01 c6                add    %rax,%rsi 270    10df:       48 d1 fe                sar    %rsi 271    10e2:       74 14                   je     10f8 0x38> 272    10e4:       48 805 05 200 00    mov    0x2f05(%rip),%rax        # 3ff0 <_ITM_registerTMCloneTable> 273    10eb:       48 85 c0                test   %rax,%rax 274    10ee:       74 08                   je     10f8 0x38> 275    10f0:       ff e0                   jmpq   *%rax 276    10f2:       66 0144 00 00       nopw   0x0(%rax,%rax,1) 277    10f8:       c3                      retq    278    10f9:       0180 00 00 00 00    nopl   0x0(%rax) 2790000000000001100 <__do_global_dtors_aux>: 280__do_global_dtors_aux(): 281    1100:       f3 01e fa             endbr64  282    1104:       80 305 200 00 00    cmpb   $0x0,0x2f05(%rip)        # 4010 <__TMC_END__> 283    110b:       75 2b                   jne    1138 <__do_global_dtors_aux+0x38> 284    110d:       55                      push   %rbp 285    110e:       48 83 3d e2 200 00    cmpq   $0x0,0x2ee2(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 286    1115:       00  287    1116:       48 89 e5                mov    %rsp,%rbp 288    1119:       74 0c                   je     1127 <__do_global_dtors_aux+0x27> 289    111b:       48 83d e6 200 00    mov    0x2ee6(%rip),%rdi        # 4008 <__dso_handle> 290    1122:       e8 19 ff ff ff          callq  1040 <__cxa_finalize@plt> 291    1127:       e8 64 ff ff ff          callq  1090 292    112c:       c6 05 dd 200 00 01    movb   $0x1,0x2edd(%rip)        # 4010 <__TMC_END__> 293    1133:       5d                      pop    %rbp 294    1134:       c3                      retq    295    1135:       0100                nopl   (%rax) 296    1138:       c3                      retq    297    1139:       0180 00 00 00 00    nopl   0x0(%rax) 2980000000000001140 : 299frame_dummy(): 300    1140:       f3 01e fa             endbr64  301    1144:       e9 77 ff ff ff          jmpq   10c0 3020000000000001149 : 303func(): 304    1149:       f3 01e fa             endbr64  305    114d:       55                      push   %rbp 306    114e:       48 89 e5                mov    %rsp,%rbp 307    1151:       805 c1 200 00       mov    0x2ec1(%rip),%eax        # 4018  308    1157:       83 c0 01                add    $0x1,%eax 309    115a:       89 05 b8 200 00       mov    %eax,0x2eb8(%rip)        # 4018  310    1160:       805 ae 200 00       mov    0x2eae(%rip),%eax        # 4014  311    1166:       83 c0 01                add    $0x1,%eax 312    1169:       89 05 a5 200 00       mov    %eax,0x2ea5(%rip)        # 4014  313    116f:       815 9200 00       mov    0x2e9f(%rip),%edx        # 4014  314    1175:       805 9200 00       mov    0x2e9d(%rip),%eax        # 4018  315    117b:       89 c6                   mov    %eax,%esi 316    117d:       48 8380 000 00    lea    0xe80(%rip),%rdi        # 2004 <_IO_stdin_used+0x4> 317    1184:       b8 00 00 00 00          mov    $0x0,%eax 318    1189:       e8 c2 fe ff ff          callq  1050 319    118e:       90                      nop 320    118f:       5d                      pop    %rbp 321    1190:       c3                      retq    3220000000000001191 : 323util_func(): 324    1191:       f3 01e fa             endbr64  325    1195:       55                      push   %rbp 326    1196:       48 89 e5                mov    %rsp,%rbp 327    1199:       48 83 ec 10             sub    $0x10,%rsp 328    119d:       89 7d fc                mov    %edi,-0x4(%rbp) 329    11a0:       845 fc                mov    -0x4(%rbp),%eax 330    11a3:       89 c6                   mov    %eax,%esi 331    11a5:       48 8372 000 00    lea    0xe72(%rip),%rdi        # 201e <_IO_stdin_used+0x1e> 332    11ac:       b8 00 00 00 00          mov    $0x0,%eax 333    11b1:       e8 9a fe ff ff          callq  1050 334    11b6:       90                      nop 335    11b7:       c9                      leaveq  336    11b8:       c3                      retq    33700000000000011b9 <main>: 338main(): 339    11b9:       f3 01e fa             endbr64  340    11bd:       55                      push   %rbp 341    11be:       48 89 e5                mov    %rsp,%rbp 342    11c1:       b8 00 00 00 00          mov    $0x0,%eax 343    11c6:       e8 7e ff ff ff          callq  1149 344    11cb:       b8 00 00 00 00          mov    $0x0,%eax 345    11d0:       e8 74 ff ff ff          callq  1149 346    11d5:       b8 00 00 00 00          mov    $0x0,%eax 347    11da:       e8 6a ff ff ff          callq  1149 348    11df:       bf 000 00 00          mov    $0xa,%edi 349    11e4:       e8 a8 ff ff ff          callq  1191 350    11e9:       e8 07 00 00 00          callq  11f5 351    11ee:       b8 00 00 00 00          mov    $0x0,%eax 352    11f3:       5d                      pop    %rbp 353    11f4:       c3                      retq    35400000000000011f5 : 355test_func(): 356    11f5:       f3 01e fa             endbr64  357    11f9:       55                      push   %rbp 358    11fa:       48 89 e5                mov    %rsp,%rbp 359    11fd:       90                      nop 360    11fe:       5d                      pop    %rbp 361    11ff:       c3                      retq    3620000000000001200 <__libc_csu_init>: 363__libc_csu_init(): 364    1200:       f3 01e fa             endbr64  365    1204:       41 57                   push   %r15 366    1206:       483d ab 200 00    lea    0x2bab(%rip),%r15        # 3db8 <__frame_dummy_init_array_entry> 367    120d:       41 56                   push   %r14 368    120f:       49 89 d6                mov    %rdx,%r14 369    1212:       41 55                   push   %r13 370    1214:       49 89 f5                mov    %rsi,%r13 371    1217:       41 54                   push   %r12 372    1219:       41 89 fc                mov    %edi,%r12d 373    121c:       55                      push   %rbp 374    121d:       48 829200 00    lea    0x2b9c(%rip),%rbp        # 3dc0 <__do_global_dtors_aux_fini_array_entry> 375    1224:       53                      push   %rbx 376    1225:       429 fd                sub    %r15,%rbp 377    1228:       48 83 ec 08             sub    $0x8,%rsp 378    122c:       e8 cf fd ff ff          callq  1000 <_init> 379    1231:       48 c1 fd 03             sar    $0x3,%rbp 380    1235:       74 1f                   je     1256 <__libc_csu_init+0x56> 381    1237:       31 db                   xor    %ebx,%ebx 382    1239:       0180 00 00 00 00    nopl   0x0(%rax) 383    1240:       489 f2                mov    %r14,%rdx 384    1243:       489 ee                mov    %r13,%rsi 385    1246:       44 89 e7                mov    %r12d,%edi 386    1249:       41 ff 14 df             callq  *(%r15,%rbx,8) 387    124d:       48 83 c3 01             add    $0x1,%rbx 388    1251:       48 39 dd                cmp    %rbx,%rbp 389    1254:       75 ea                   jne    1240 <__libc_csu_init+0x40> 390    1256:       48 83 c4 08             add    $0x8,%rsp 391    125a:       5b                      pop    %rbx 392    125b:       5d                      pop    %rbp 393    125c:       41 5c                   pop    %r12 394    125e:       41 5d                   pop    %r13 395    1260:       41 5e                   pop    %r14 396    1262:       41 5f                   pop    %r15 397    1264:       c3                      retq    398    1265:       66 66 20184 00    data16 nopw %cs:0x0(%rax,%rax,1) 399    126c:       00 00 00 00  4000000000000001270 <__libc_csu_fini>: 401__libc_csu_fini(): 402    1270:       f3 01e fa             endbr64  403    1274:       c3                      retq    404Disassembly of section .fini: 4050000000000001278 <_fini>: 406_fini(): 407    1278:       f3 01e fa             endbr64  408    127c:       48 83 ec 08             sub    $0x8,%rsp 409    1280:       48 83 c4 08             add    $0x8,%rsp 410    1284:       c3                      retq @plt>@plt>++++@plt>老规矩,看不懂全部不重要,找你能看得懂的。还是找到 l_count 、g_count、util_test 这几个来吧。RT-Thread看样子也没啥特殊的,所以问题的关键还在前一步:链接器那里。综上可知,static的修饰主要是给编译器做了提示,从而生成的obj文件中带了 local属性,这样就告诉链接器,不能扩大这些被local修饰过的内容的使用范围,从而达到了教科书上面说的那样static的作用效果。其实还有一个方法,就是你写一个带static和不带static的,比如都是全局变量的两个,通过反汇编来对比分析,这样也可以快速看出核心区别,就留给读者去探索吧。再留一个疑问:编译器、链接器 如何做到一个static修饰的局部变量,只能被定义的当前函数内访问的?这个问题,有点深入,也留给读者去探索吧。
		 5 一种绕开static限制的方法
谈到绕开static的限制,其实本文第1小节的那个问题例子就是一个很好的思路和方法。要想绕开static的限制,无非就是:将被static修饰的函数转换为没有被static修饰的函数!或者将被static修饰的变量转换为没有被static修饰的变量!这个做法,还有一个行业名词叫:封装在第1小节中,代码中演示的是将被static修饰的变量,通过传出其地址,以指针的形式导出给外部模块使用。下面的代码片段,将展示将被static修饰的函数,转换为没有被static修饰的函数,从而给外部模块使用。

		1test_a.c  2static int test_func_in_a(int a)  3{  4    return a + 1;  5}  6int test_func_in_a_ex(int a)  7{  8    return test_func_in_a(a);  9} 10---------------------------- 11test_b.c 12int test_func_in_b(void) 13{ 14    int a = 1; 15    int b; 16    //call test_func_in_a function fail because of "static" 17    //b = test_func_in_a(a) 18    //call test_func_in_a_ex function ok without "static" 19    b = test_func_in_a_ex(a) 20    return b; 21}示例代码很简单,仅仅就是在_test_a.c 中,编写一个不被static修饰的函数 test_func_in_a_ex,然后它去调用被static修饰的test_func_in_a函数,这样就轻松绕开了static的限制。你学会了吗?
		 6 拓展延伸:如何调用静态库里的被static修饰的函数?
关于这个扩展延伸,其实我很早就起草了一篇博文想写这个内容来着,但是一直拖,一直拖,直到现在还没生产。索性就在本文做个牵引吧!个人认为,对于此问题,应该分为两个场景:静态库的代码,你有修改的权限;或者你能找到人来修改;比如,公司内部不同团队直接的公有库代码;静态库的代码,你完全没办法查看源码或修改源码;比如一些第三方的库。针对这两种不同的场景,可能采取的方式是不一样的,你觉得应该如何做最好呢?如果你也对此问题感兴趣,请关注我的后续的拆解博文。

原文:https://club.rt-thread.org/ask/article/1b38085300b58f82.html

作者:recan

 

———————End——————

 

 


 

 

点击阅读原文进入官网

​​​​​​


原文标题:【知识科普】C语言的static究竟限制了谁

文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分