zoukankan      html  css  js  c++  java
  • gcc编译的东东

    1.分析普通的helloworld程序
         先书写一下一个简单的helloworld程序如下:
    /* hello.c */
    int main(int argc, char * argv[])
    {
        return 0
    }
         编译程序:
    gcc -o hello hello.c
         等价的编译方法:
    gcc -c hello.c
    gcc -o hello.my -nostartfiles hello.o /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtn.o
         我在redflag workstation 5.0版本下用3.4.3版本GCC编译器编译出来的大小都是3589字节,并且用diff命令比较为相同的文件。由此证明gcc在编译并链接 hello.c文件时先将hello.c编译成hello.o,然后将它与crt1.o、crti.o、crtn.o链接在一起。

         如果要写一个没有main函数的程序,就需要自己实现crt1.o。程序入口为符号“_start”处。代码如下:
    /* nomain.c */
    void _start(void)
    {
         _exit(0);
    }
    gcc -o nomain -nostartfiles hello.c

    2.编译和使用库
         除了直接编译代码外还会使用到函数库。库有静态库和动态库之分。静态库是以.a结尾的文件,例如:libXXX.a;动态库是以.so结尾的文件,例如: libXXX.so。XXX之后或者.so和.a之后会跟版本号,例如:libc-2.3.4.so,或者libuuid.so.1.2。
         加入函数库的代码如下:
    /* test.h */
    int test1 (void);

    /* test.c */
    #include <stdio.h>
    #include "libtest.h"

    int test1 (void)
    {
        printf("test1 function is called.\n");
        return 0;
    }
         当要编译成静态库的时候使用如下命令生成libtest.a:
    gcc -c test.c
    ar -r libtest.a test.o
         当要编译成动态链接库的时候使用如下命令生成libtest.so
    gcc -c -fpic test.c
    gcc -shared test.o -o libtest.so

    gcc -fpic -shered test.c -o libtest.so
         当需要调用该库时使用如下代码。
    /* calllib.c */
    #include "test.h"

    int main (int argc, char * argv[])
    {
         test1();
    }
         按如下方式编译:
    gcc -o calllib.static calllib.c libtest.a

    gcc -o calllib.dynamic calllib.c libtest.so

    gcc -o calllib calllib.c -ltest
         前提是libtest.a或libtest.so在当前编译的目录。
         使用ldd显示calllib.static依赖的库只有libc和ld-linux,但calllib.dynamic就多了一个libtest.so。


    3.库文件和头文件
         在程序中,使用#include <stdio.h>类似的头文件stdio.h在编译器的头文件路径中,#include "abc.h"中的stdio.h文件则应该在当前目录。通过对编译器指定参数-I<PATH>来指定头文件所在目录,可以用 #include <>来引用。例如:gcc -I./include hello.c,将从当前目录下的include目录下去寻找头文件。
         同理,程序中调用的库函数在编译时也需要指定路径,同时指定库。使用-L<PATH>参数指定库文件的目录,-l<FILE>指定包含的库文件。例如,要使用libXXX.so库,参数为-lXXX。
         一般一个库编译完成后有库文件和头文件。如果要使用这个库,可以将库文件目录和头文件目录分别用-I和-L参数指定,也可以将他们拷贝到编译器的include和lib目录下。


    4.缩小程序体积
         代码如下:
    /* nomain.c */
    void _start(void)
    {
        asm("movl , eax\n"
            "movl {fckeditor}, ebx\n"
            "int {fckeditor}x80"
        );
    }
    使用如下方法能使可执行文件体积最小(手工方法除外)。
    gcc -o nomain -s -O3 nomain.c
    objcopy -R .comment -R .data
         由此得到可执行文件的体积为352字节。


         GCC能编译出2种格式的可执行体:a.out格式、elf格式。其中.o目标文件、.a静态库文件

    Appendix.1 常用命令
    ldd:显示可执行文件或者库文件依赖的库文件。
    objdump:显示elf可执行文件的内部信息。
        -h:显示
        -t:显示符号信息
        -T:显示动态符号信息。(例如引用动态链接库中的函数名称)
        -r:显示重定位入口信息。
        -R:显示动态重定位入口信息。(例如:动态链接库中的变量或者函数地址)
        -s:显示所有section内容。
        -S:反汇编代码段。
    objcopy:copy elf文件内容
        -R:删除某个section
        -j:仅仅复制指定的section
  • 相关阅读:
    有用的网站
    RMVANNUAL matlab remove annual cycle of a time series
    [转载]grdcontour命令在GMT4下绘制等值线图
    Filter应用之-自动登录
    Filter应用之-验证用户是否已经登录
    Filter应用之2-设置某些页面缓存或是不缓存
    过虑器应用之1-设置request编码
    过滤器Filter
    java文件下载
    用COS实现文件上传
  • 原文地址:https://www.cnblogs.com/danghuijian/p/4400854.html
Copyright © 2011-2022 走看看