精华内容
下载资源
问答
  • 程序链接程序链接1、链接是什么?2、链接器通过什么进行的链接?3、为什么需要extern "C"?参考 程序链接 源代码(source coprede)→预处理器(processor)→编译器(compiler)→汇编程序(assembler)→目标...

    程序链接

    源代码(source coprede)→预处理器(processor)→编译器(compiler)→汇编程序(assembler)→目标程序(object code)→链接器(Linker)→可执行程序(executables)
    在这里插入图片描述
    分配程序执行所需的栈空间、代码段、静态存储区、映射堆空间地址等,操作系统会创建一个进程结构体来管理进程,然后将进程放入就绪队列,等待CPU调度运行。

    1、链接链的是什么?

    链接链的就是目标文件,什么是目标文件?目标文件就是源代码编译后但未进行链接的那些中间文件,如Linux下的.o,它和可执行文件的内容和结构很相似,格式几乎是一样的,可以看成是同一种类型的文件,Linux下统称为ELF文件,这里介绍下ELF文件标准:

    • 1、可重定位文件Linux中的.o,这类文件包含代码和数据,可被链接成可执行文件或共享目标文件,例如静态链接库。
    • 2、可执行文件可以直接执行的文件,如/bin/bash文件。
    • 3、共享目标文件Linux中的.so,包含代码和数据,一种是链接器可以使用这种文件和其它的可重定位文件和共享目标文件链接,另一种是动态链接器可以将几个这种共享目标文件和可执行文件结合,作为进程映像的一部分来执行。
    • 4、core dump文件:进程意外终止时,系统可以将该进程的地址空间的内容和其它信息存到coredump文件用于调试,如gdb。

    我们可以使用command file来查看文件的格式:

    file test.o; file /bin/bash;
    

    目标文件的构成

    目标文件主要分为文件头、代码段、数据段和其它。

    • 文件头:描述整个文件的文件属性(文件是否可执行、是静态链接还是动态链接、入口地址、目标硬件、目标操作系统等信息),还包括段表,用来描述文件中各个段的数组,描述文件中各个段在文件中的偏移位置和段属性。
    • 代码段:程序源代码编译后的机器指令。
    • 数据段:数据段分为.data段和.bss段。
    • .data段内容:已经初始化的全局变量和局部静态变量
    • .bss段内容:未初始化的全局变量和局部静态变量,.bss段只是为未初始化的全局变量和局部静态变量预留位置,本身没有内容,不占用空间。
    • 除了代码段和数据段,还有.rodata段、.comment、字符串表、符号表和堆栈提示段等等,还可以自定义段。

    2、链接器通过什么进行的链接?

    链接的接口是符号,在链接中,将函数和变量统称为符号函数名和变量名统称为符号名。链接过程的本质就是把多个不同的目标文件之间相互“粘”到一起,像玩具积木一样各有凹凸部分,有固定的规则可以拼成一个整体。

    可以将符号看作是链接中的粘合剂,整个链接过程基于符号才可以正确完成,符号有很多类型,主要有局部符号和外部符号:

    • 局部符号只在编译单元内部可见,对于链接过程没有作用
    • 在目标文件中引用的全局符号,却没有在本目标文件中被定义的叫做外部符号,以及定义在本目标文件中的可以被其它目标文件引用的全局符号,在链接过程中发挥重要作用。

    可以使用一些命令来查看符号信息:

    command nm:
    
    $ nm test.o
                     U _GLOBAL_OFFSET_TABLE_
    0000000000000000 T main
                     U puts
    
    command objdump:
    
    objdump -t test.o
    
    test.o:     file format elf64-x86-64
    
    SYMBOL TABLE:
    0000000000000000 l    df *ABS*  0000000000000000 test_c.cc
    0000000000000000 l    d  .text  0000000000000000 .text
    0000000000000000 l    d  .data  0000000000000000 .data
    0000000000000000 l    d  .bss   0000000000000000 .bss
    0000000000000000 l    d  .rodata        0000000000000000 .rodata
    0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
    0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
    0000000000000000 l    d  .comment       0000000000000000 .comment
    0000000000000000 g     F .text  0000000000000017 main
    0000000000000000         *UND*  0000000000000000 _GLOBAL_OFFSET_TABLE_
    0000000000000000         *UND*  0000000000000000 puts
    
    command readelf:
    
    readelf -s test.o
    
    Symbol table '.symtab' contains 12 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test_c.cc
         2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
         3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
         4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
         5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
         6: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
         7: 0000000000000000     0 SECTION LOCAL  DEFAULT    8
         8: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
         9: 0000000000000000    23 FUNC    GLOBAL DEFAULT    1 main
        10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
        11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND puts
    

    3、为什么需要extern “C”?

    • C语言函数和变量的符号名基本就是函数名字变量名字,不同模块如果有相同的函数或变量名字就会产生符号冲突无法链接成功的问题
    • C++引入了命名空间来解决这种符号冲突问题。同时为了支持函数重载C++也会根据函数名字以及命名空间以及参数类型生成特殊的符号名称。
    • 由于C语言和C++的符号修饰方式不同,C语言和C++的目标文件在链接时可能会报错说找不到符号,所以为了C++和C兼容,引入了extern "C"
    • 当引用某个C语言的函数时加extern "C"告诉编译器对此函数使用C语言的方式来链接,如果C++的函数用extern
      "C"声明,则此函数的符号就是按C语言方式生成的。

    以memset函数举例,C语言中以C语言方式来链接,但是在C++中以C++方式来链接就会找不到这个memset的符号,所以需要使用extern "C"方式来声明这个函数,为了兼容C和C++,可以使用宏来判断,用条件宏判断当前是不是C++代码,如果是C++代码则extern “C”。

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    void *memset(void *, int, size_t);
    
    #ifdef __cplusplus
    }
    #endif
    

    参考

    1、https://zhuanlan.zhihu.com/p/145263213

    展开全文
  • 什么是链接,为什么需要链接?

    千次阅读 2020-05-27 16:06:12
    什么需要链接 在实际开发中,我们一定多文件编程,所有...把组合C文件编译成汇编文件.s,目标文件为机器指令(放在一个.o文件当中),单个目标文件不能工作的,因为各个目标文件相互支撑工作的。 把各个...

    为什么需要链接

              在实际开发中,我们一定是多文件编程,所有文件在编译后,需要合在一起,合在一起的过程就是链接的过程。

             每一个源文件(就是.c文件,上图中的程序1)都有对应的零碎文件(就是.h文件),通过预编译(通过#include实现)把.c和.h文件整合成一个组合C文件,这个组合C文件的扩展名为.i。把组合C文件编译成汇编文件.s,目标文件为机器指令(放在一个.o文件当中),单个目标文件是不能工作的,因为各个目标文件是相互支撑工作的。

             把各个目标文件整合的过程就叫链接过程。整合后的文件就叫可执行程序,windows后缀为.exe,Linux后缀为.out

    链接过程都干了什么事

               目标文件主要分为两个区域:数据区域和指令区域。 每一个指令和数据都被安排了地址。

             (1)地址重定位: 目标文件被整合的时候,每个目标文件的数据区被整合到一起,每个目标文件的指令区被整合到一起。假如目标文件1被整合前指令的地址是00000001,目标文件n整合前指令的地址也是00000001,整合到一起后,他们的地址是要重新编排的,这个叫地址重定位。数据区域的地址相应的也要重新编排。

               重定位地址的作用:CPU会通过这个重定位的地址进行寻址,找到在内存中要执行的指令和数据,然后取出指令执行,并按照指令要求处理数据。重定位以后,会给执行文件中的计算机指令数据,重新安排地址,CPU会通过这些地址取指令执行,并处理这些数据。最终需要通过这些地址找到内存中的指令和数据。

               链接脚本:重定位时,这个重定位的地址是如何安排的呢,需要使用一个链接脚本文件,这个文件中会有重定位地址的说明,重定位时,会按照这个脚本的重定位地址的要求,来进行地址重定位工作。

            

             (2) 符号统一 :   直接举个C语言中的例子,假设程序有两个.c文件,分别是a.c和b.c,这两个文件中都有名叫var的变量,a.c被编译得到a.o,b.c被编译得到b.o,将a.o和b.o链接到同一个文件时,var命名重复了,需要根据规则对着两个符号进行统一,与此相似的还有函数名的“符号统一”问题。

     

     

    展开全文
  • 1.一般来说,无论是C、C++,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下 .o 文件,即 Object File。 2.在编译时编译器需要的语法的正确,函数与变量的声明的正确。只要所有的语法...

    编译:

    1.一般来说,无论是C、C++,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File。
    2.在编译时编译器需要的是语法的正确函数与变量的声明的正确。只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。

    链接:

    1.链接主要是链接函数和全局变量,链接器会在所有的Object File中找寻函数的实现。
    2.链接将所有二进制形式的目标文件和系统组件(比如标准库、动态链接库等)组合成一个可执行文件

    流程图:

    在这里插入图片描述引用sky_Mata 的图片

    展开全文
  • linux服务器开发相关视频...什么是地址无关代码技术? 什么是延迟绑定技术? 如何在程序运行过程中进行显式链接? 为什么要进行动态链接? 因为静态链接有缺点: 1、浪费内存和磁盘空间:如下图, Program1和Program

    linux服务器开发相关视频解析:

    网络底层io的那些事,redis,memcached,nginx
    基于linux epoll原理剖析以及三握四挥的细节处理

    c/c++ linux服务器开发免费学习地址:c/c++ linux后台服务器高级架构师

    先抛出几个问题:

    • 为什么要进行动态链接?
    • 如何进行动态链接?
    • 什么是地址无关代码技术?
    • 什么是延迟绑定技术?
    • 如何在程序运行过程中进行显式链接?

    为什么要进行动态链接?

    因为静态链接有缺点:
    1、浪费内存和磁盘空间:如下图,在这里插入图片描述
    Program1和Program2分别包含Program1.o和Program2.o两个模块,他们都需要Lib.o模块。静态链接情况下,两个目标文件都用到Lib.o这个模块,所以它们同时在链接输出的可执行文件Program1和program2中有副本,同时运行时,Lib.o在磁盘和内存中有两份副本,当系统中有大量类似Lib.o的多个程序共享目标文件时,就会浪费很大空间。

    2、静态链接对程序的更新部署和发布很不友好:假如一个模块依赖20个模块,当20个模块其中有一个模块需要更新时,需要将所有的模块都找出来重新编译出一个可执行程序才可以更新成功,每次更新任何一个模块,用户就需要重新获得一个非常大的程序,程序如果使用静态链接,那么通过网络来更新程序也会非常不便,一旦程序任何位置有一个小改动,都会导致整个程序重新下载。

    为了解决静态链接的缺点,所以引入了动态链接,动态链接的内存分布如图,在这里插入图片描述
    多个程序依赖同一个共享目标文件,这个共享目标文件在磁盘和内存中仅有一份,不会产生副本,简单来讲就是不像静态链接一样对那些组成程序的目标文件进行链接,等到程序要运行时才进行链接,把链接这个过程推迟到运行时才执行。动态链接的方式使得开发过程中各个模块更加独立,耦合度更小,便于不同的开发者和开发组织之间独立的进行开发和测试。

    如何进行动态链接?

    看如下代码:

    // lib.c
    #include <stdio.h>
    
    void func(int i) {
       printf("func %d \n", i);
    }
    
    // Program.c
    void func(int i);
    
    int main() {
       func(1);
       return 0;
    }
    

    编译运行过程如下:

    $ gcc -fPIC -shared -o lib.so lib.c
    $ gcc -o test Program.c ./lib.so
    $ ./test
    $ func 1
    

    通过-fPIC和-shared可以生成一个动态链接库,再链接到可执行程序就可以正常运行。

    通过readelf命令可以查看动态链接库的segment信息:

    ~/test$ readelf -l lib.so
    
    Elf file type is DYN (Shared object file)
    Entry point 0x530
    There are 7 program headers, starting at offset 64
    
    Program Headers:
     Type           Offset             VirtAddr           PhysAddr
                    FileSiz            MemSiz              Flags  Align
     LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                    0x00000000000006e4 0x00000000000006e4  R E    0x200000
     LOAD           0x0000000000000e10 0x0000000000200e10 0x0000000000200e10
                    0x0000000000000218 0x0000000000000220  RW     0x200000
     DYNAMIC        0x0000000000000e20 0x0000000000200e20 0x0000000000200e20
                    0x00000000000001c0 0x00000000000001c0  RW     0x8
     NOTE           0x00000000000001c8 0x00000000000001c8 0x00000000000001c8
                    0x0000000000000024 0x0000000000000024  R      0x4
     GNU_EH_FRAME   0x0000000000000644 0x0000000000000644 0x0000000000000644
                    0x0000000000000024 0x0000000000000024  R      0x4
     GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                    0x0000000000000000 0x0000000000000000  RW     0x10
     GNU_RELRO      0x0000000000000e10 0x0000000000200e10 0x0000000000200e10
                    0x00000000000001f0 0x00000000000001f0  R      0x1
    
    Section to Segment mapping:
     Segment Sections...
      00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
      01     .init_array .fini_array .dynamic .got .got.plt .data .bss
      02     .dynamic
      03     .note.gnu.build-id
      04     .eh_frame_hdr
      05
      06     .init_array .fini_array .dynamic .got
    

    可以看见动态链接模块的装载地址从0开始,0是无效地址,它的装载地址会在程序运行时再确定,在编译时是不确定的。

    改一下程序:

    // Program.c
    #include <stdio.h>
    void func(int i);
    
    int main() {
       func(1);
       sleep(-1);
       return 0;
    }
    

    运行读取maps信息:

    ~/test$ ./test &
    [1] 126
    ~/test$ func 1
    cat /proc/126/maps
    7ff2c59f0000-7ff2c5bd7000 r-xp 00000000 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
    7ff2c5bd7000-7ff2c5be0000 ---p 001e7000 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
    7ff2c5be0000-7ff2c5dd7000 ---p 000001f0 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
    7ff2c5dd7000-7ff2c5ddb000 r--p 001e7000 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
    7ff2c5ddb000-7ff2c5ddd000 rw-p 001eb000 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
    7ff2c5ddd000-7ff2c5de1000 rw-p 00000000 00:00 0
    7ff2c5df0000-7ff2c5df1000 r-xp 00000000 00:00 189022             /mnt/d/wzq/wzq/util/test/lib.so
    7ff2c5df1000-7ff2c5df2000 ---p 00001000 00:00 189022             /mnt/d/wzq/wzq/util/test/lib.so
    7ff2c5df2000-7ff2c5ff0000 ---p 00000002 00:00 189022             /mnt/d/wzq/wzq/util/test/lib.so
    7ff2c5ff0000-7ff2c5ff1000 r--p 00000000 00:00 189022             /mnt/d/wzq/wzq/util/test/lib.so
    7ff2c5ff1000-7ff2c5ff2000 rw-p 00001000 00:00 189022             /mnt/d/wzq/wzq/util/test/lib.so
    7ff2c6000000-7ff2c6026000 r-xp 00000000 00:00 516353             /lib/x86_64-linux-gnu/ld-2.27.so
    7ff2c6026000-7ff2c6027000 r-xp 00026000 00:00 516353             /lib/x86_64-linux-gnu/ld-2.27.so
    7ff2c6227000-7ff2c6228000 r--p 00027000 00:00 516353             /lib/x86_64-linux-gnu/ld-2.27.so
    7ff2c6228000-7ff2c6229000 rw-p 00028000 00:00 516353             /lib/x86_64-linux-gnu/ld-2.27.so
    7ff2c6229000-7ff2c622a000 rw-p 00000000 00:00 0
    7ff2c62e0000-7ff2c62e3000 rw-p 00000000 00:00 0
    7ff2c62f0000-7ff2c62f2000 rw-p 00000000 00:00 0
    7ff2c6400000-7ff2c6401000 r-xp 00000000 00:00 189023             /mnt/d/wzq/wzq/util/test/test
    7ff2c6600000-7ff2c6601000 r--p 00000000 00:00 189023             /mnt/d/wzq/wzq/util/test/test
    7ff2c6601000-7ff2c6602000 rw-p 00001000 00:00 189023             /mnt/d/wzq/wzq/util/test/test
    7fffee96f000-7fffee990000 rw-p 00000000 00:00 0                 [heap]
    7ffff6417000-7ffff6c17000 rw-p 00000000 00:00 0                 [stack]
    7ffff729d000-7ffff729e000 r-xp 00000000 00:00 0   
    

    可以看到,整个进程虚拟地址空间中,多出了几个文件的映射,lib.so和test一样,它们都是被操作系统用同样的方法映射到进程的虚拟地址空间,只是它们占据的虚拟地址和长度不同,从maps里可以看见里面还有libc-2.27.so,这是C语言运行库,还有一个ld-2.27.so,这是Linux下的动态链接器,动态链接器和普通共享对象一样被映射到进程的地址空间,在系统开始运行test前,会先把控制权交给动态链接器,动态链接器完成所有的动态链接工作后会把控制权交给test,然后执行test程序。

    当链接器将Program.o链接成可执行文件时,这时候链接器必须确定目标文件中所引用的func函数的性质,如果是一个定义于其它静态目标文件中的函数,那么链接器将会按照静态链接的规则,将Program.o的func函数地址进行重定位,如果func是一个定义在某个动态链接共享对象中的函数,那么链接器将会将这个符号的引用标记为一个动态链接的符号,不对它进行地址重定位,将这个过程留在装载时再进行。
    【文章福利】需要C/C++ Linux服务器架构师学习资料加群812855908(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)
    在这里插入图片描述

    动态链接的方式

    动态链接有两种方式:装载时重定位和地址无关代码技术。

    装载时重定位:在链接时对所有绝对地址的引用不作重定位,而把这一步推迟到装载时完成,也叫基址重置,每个指令和数据相当于模块装载地址是固定的,系统会分配足够大的空间给装载模块,当装载地址确定后,那指令和数据地址自然也就确定了。然而动态链接模块被装载映射到虚拟空间,指令被重定位后对于每个进程来讲是不同的,没有办法做到同一份指令被多个进程共享,所以指令对不同的进程来说有不同的副本,还是空间浪费,怎么解决这个问题?使用fPIC方法。

    地址无关代码:指令部分无法在多个进程之间共享,不能节省内存,所以引入了地址无关代码的技术。我们平时编程过程中可能都见过-fPIC的编译选项,这个就代表使用了地址无关代码技术来实现真正的动态链接。基本思想就是使用GOT(全局偏移表),这是一个指向变量或函数地址的指针数组,当指令要访问变量或者调用函数时,会去GOT中找到相应的地址进行间接跳转访问,每个变量或函数都对应一个地址,链接器在装载模块的时候会查找每个变量和函数的地址,然后填充GOT中的各个项,确保每个指针指向的地址正确。GOT放在数据段,所以它可以在模块装载时被修改,并且每个进程都可以有独立的副本,相互不受影响。

    tips

    -fpic和-fPIC的区别:它们都是地址无关代码技术,-fpic产生的代码相对较小较快,但是在某些平台会有些限制,所以大多数情况下都是用-fPIC来产生地址无关代码。

    -fPIC和-fPIE的区别:一个作用于共享对象,一个作用于可执行文件,一个以地址无关方式编译的可执行文件被称作地址无关可执行文件。

    -fpie和-fPIE的区别:类似于-fpic和-fPIC的区别
    延迟绑定技术

    在程序刚启动时动态链接器会寻找并装载所需要的共享对象,然后进行符号地址寻址重定位等工作,这些工作会减慢程序的启动速度,如果解决?

    使用PLT延迟绑定技术,这里会单独有一个叫.PLT的段,ELF将 GOT拆分成两个表.GOT和.GOT.PLT,其中.GOT用来保存全局变量的引用地址,.GOT.PLT用来保存外部函数的地址,每个外部函数在PLT中都有一个对应项,在初始化时不会绑定,而是在函数第一次被用到时才进行绑定,将函数真实地址与对应表项进行绑定,之后就可以进行间接跳转。

    显式运行时链接

    支持动态链接的系统往往都支持显式运行时链接,也叫运行时加载,让程序自己在运行时控制加载的模块,在需要时加载需要的模块,在不需要时将其卸载。这种运行时加载方式使得程序的模块组织变得很灵活,可以用来实现一些诸如插件、驱动等功能。

    通过这四个API可以进行显式运行时链接:

    dlopen():打开动态链接库
    dlsym():查找符号
    dlerror():错误处理
    dlclose():关闭动态链接库

    参考这段使用代码:

    #include <stdio.h>
    #include <dlfcn.h>
    
    int main() {
       
       void *handle;
       void (*f)(int);
       char *error;
    
       handle = dlopen("./lib.so", RTLD_NOW);
       if (handle == NULL) {
           printf("handle null \n");
           return -1;
      }
       f = dlsym(handle, "func");
       do {
           if ((error = dlerror()) != NULL) {
               printf("error\n");
               break;
          }
           f(100);
      } while (0);
       dlclose(handle);
    
       return 0;
    }
    

    编译运行:

    $ gcc -o test program.c -ldl
    $ ./test
    func 100
    

    总结

    为什么要进行动态链接?为了解决静态链接浪费空间和更新困难的缺点。

    动态链接的方式?装载时重定位和地址无关代码技术。

    地址无关代码技术原理?通过GOT段实现间接跳转。

    延迟加载技术原理?对外部函数符号通过PLT段实现延迟绑定及间接跳转。

    如果进行显式运行时链接?通过<dlfcn.h>头文件中的四个函数,代码如上。

    展开全文
  • 原型链是什么样的?

    2017-07-12 12:24:00
    原型链是什么链呢? 简单说下自己的理解: 每个对象都有一个原型对象. 原型对象中存放这这个对象的属性和方法. 每个对象都有一个指针_proto_. 指向自己的原型对象. 每个对象都有一个prototype属性. 这个属性是一个...
  • 什么是链接? 对于初学C语言的朋友,可能对链接这个概念有点陌生,这里简单介绍一下。我们的C代码编译生成可执行程序会经过如下过程: 链接就是把目标文件与一些库文件生成可执行文件的一个过程。关于更详细的编译...
  • 什么是作用域什么是原型。  作用域针对变量的,比如我们创建了一个函数,函数里面又包含了一个函数,那么现在就有三个作用域  全局作用域==>函数1作用域==>函数2作用域 作用域的特点就是,先在自己...
  • 什么是供应

    2012-10-31 12:46:00
    什么是供应 供应,由供应商、制造商、仓库、配送中心和渠道商等构成的物流网络。 所谓供应管理,就是指在满足一定的客户服务水平的条件下,为了使整个供应系统成本达到最小而把供应商、制造商、仓库、...
  • 头文件包含函数定义,链接根据头文件链接到包含函数体的库文件。 转载于:https://www.cnblogs.com/Bird-Xu/p/6966100.html
  • 构造函数 在 c++ 中,我们可以知道,类事物的抽象,通过类可以生成一个个实例化的具体对象,类提供着生成对象的“模板”。在 JavaScript 中构造函数(constructor)就起着“模板”的作用,通过构造函数,我们...c...
  • 电子束辐射电缆护套的塑料部分。... 换言之,电子束将在以下方面改变塑料的聚合结构: 增强耐热性(可将温度范围扩大自70°C至100°C以上,或更高) 增强机械稳定性,增强化学稳定性。 来源:ks99
  • <div><p>我发现代码里<code>genFLVDiv函数中࿰c;如果不是bangumi࿰c;则会将已有的“复制下载链接”替换成“到处idm”?这个设计的原因? 我个人使用aria2࿰c;所以更喜欢复制下载链接ÿ...
  • <div><p>就是这个id:000OjsEW0QrPAd ...000OjsEW0QrPAd&...这什么呀࿰c;不止这首歌 ࿰c;有小量歌曲会出现解析其他版本问题</p><p>该提问来源于开源项目:jsososo/NeteaseMusic</p></div>
  • 链接器做什么

    千次阅读 2015-07-21 15:00:23
    讨论的背景主要基于C/C++,Linux平台相关。 链接器相关的一些基本问题  学习或者了解链接器,有一些基本的问题需要关心:链接器做些什么;链接器和体系结构;程序怎样生成的。下面做简要介绍。
  • http://c.biancheng.net/blockchain/ 延伸阅读,区块链的实际应用: https://www.jianshu.com/p/b27fac2e734f 当有一天我们相信阿里和政府一样不可以崩塌的时候,就像相信比特币的系统一直只有人类毁灭才会...
  • 列表循环添加链接Here you will get program for circular linked list in C. 在这里,您将获得C中循环链表的... 什么是循环链表? A circular linked list is a linked list in which the last node points to ...
  • C++/C链接过程详解

    2015-06-04 14:35:56
    C++/C链接过程详解 有 些人写C/C++(以下假定为C++)程序,对...或者对语言的一些部分不知道为什么要(或者不要)这样那样设计。了解本文之后, 或许会有一些答案。   首先看看我们如何写一个程序的。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,130
精华内容 2,452
关键字:

c链是什么