Linux c编程之gcc

一、gcc介绍

  gcc是linux平台的C语言编译器,也是一个可执行程序。在linux平台也可以编译arm平台的可执行程序,一般用交叉编译器,如arm-xx-linux-gcc。

二、参数说明

-v: 查看gcc的版本
-c: 编译为目标文件,不链接库
-S: 编译为汇编代码
-E 预处理
-Wwarn: 设置警告
-Olevel:设计 优化级别可以是0,1,2,3或者S, 默认-O0, 即不进行优化
-Dname=value, 设置宏定义,用于调试
-Uname:取消宏定义
-I 指定额外的头文件搜索路径,gcc会在搜索标准头文件之前先搜索额外的头文件路径
-l: 链接库(动态库或静态库)
-std=standard: 设置采用的标准, 如-std=c99表示编译器遵循C99标准
-o outfile: 指定输出文件的文件名,默认输出为a.out
-g: 打开调试选项,编译出的可执行文件可以使用gdb进行调试
–static: 链接静态库, gcc编译时默认链接动态库

三、编译过程

  gcc编译时可以一条命令直接生成可执行文件,而实际的编译过程中是分为四个阶段。如下:

  1. 预处理
    在预处理阶段,输入的是C语言文件,这个阶段主要处理源文件中的#ifdef
    #include和#define等预处理命令,比如宏定义值被展开替换。一般生成中间文件*.i。
  2. 编译
    生成汇编语言文件*s
  3. 汇编
    将输入的汇编文件*.s转换成二进制机器代码*.o
    4.链接
    将输入的二进制机器代码文件*.o链接为一个可执行的二进制代码文件
    以编译以下hello_world_main.c为例:
    一个命令生成 可执行文件:
    $ gcc hello_world_main.c -o a.out
    分阶段编译:
    1 预处理
$ gcc -E hello_world_main.c -o hello_world_main.i

  从hello_world_main.i中可以看到宏定义SIZE已经被替换为真实值5了,如下:

# 2 "hello_world_main.c" 2
int main(int argc, char *argv[])
{
    printf("hello world, value: %d\n", 5);

    return 0;
}

2 编译

gcc -S hello_world_main.i -o hello_world_main.s

hello_world_main.s:

.file	"hello_world_main.c"
	.section	.rodata
.LC0:
	.string	"hello world, value: %d\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	%edi, -4(%rbp)
	movq	%rsi, -16(%rbp)
	movl	$5, %esi
	movl	$.LC0, %edi
	movl	$0, %eax
	call	printf
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
	.section	.note.GNU-stack,"",@progbits

3 汇编

$ gcc -c hello_world_main.s -o hello_world_main.o
$ hexdump hello_world_main.o
0000000 457f 464c 0102 0001 0000 0000 0000 0000
0000010 0001 003e 0001 0000 0000 0000 0000 0000
0000020 0000 0000 0000 0000 0150 0000 0000 0000
0000030 0000 0000 0040 0000 0000 0040 000d 000a
0000040 4855 e589 8348 10ec 7d89 48fc 7589 bef0
0000050 0005 0000 00bf 0000 b800 0000 0000 00e8
0000060 0000 b800 0000 0000 c3c9 6568 6c6c 206f
0000070 6f77 6c72 2c64 7620 6c61 6575 203a 6425
0000080 000a 4700 4343 203a 5528 7562 746e 2075
0000090 2e34 2e38 2d34 7532 7562 746e 3175 317e
00000a0 2e34 3430 2029 2e34 2e38 0034 0000 0000
00000b0 0014 0000 0000 0000 7a01 0052 7801 0110
00000c0 0c1b 0807 0190 0000 001c 0000 001c 0000
00000d0 0000 0000 002a 0000 4100 100e 0286 0d43
00000e0 6506 070c 0008 0000 2e00 7973 746d 6261
00000f0 2e00 7473 7472 6261 2e00 6873 7473 7472
0000100 6261 2e00 6572 616c 742e 7865 0074 642e
0000110 7461 0061 622e 7373 2e00 6f72 6164 6174
0000120 2e00 6f63 6d6d 6e65 0074 6e2e 746f 2e65
0000130 4e47 2d55 7473 6361 006b 722e 6c65 2e61
0000140 6865 665f 6172 656d 0000 0000 0000 0000
0000150 0000 0000 0000 0000 0000 0000 0000 0000
*
0000190 0020 0000 0001 0000 0006 0000 0000 0000
00001a0 0000 0000 0000 0000 0040 0000 0000 0000
00001b0 002a 0000 0000 0000 0000 0000 0000 0000
00001c0 0001 0000 0000 0000 0000 0000 0000 0000
00001d0 001b 0000 0004 0000 0000 0000 0000 0000
00001e0 0000 0000 0000 0000 05b8 0000 0000 0000
00001f0 0030 0000 0000 0000 000b 0000 0001 0000
0000200 0008 0000 0000 0000 0018 0000 0000 0000
0000210 0026 0000 0001 0000 0003 0000 0000 0000
0000220 0000 0000 0000 0000 006a 0000 0000 0000
0000230 0000 0000 0000 0000 0000 0000 0000 0000
0000240 0001 0000 0000 0000 0000 0000 0000 0000
0000250 002c 0000 0008 0000 0003 0000 0000 0000
0000260 0000 0000 0000 0000 006a 0000 0000 0000
0000270 0000 0000 0000 0000 0000 0000 0000 0000
0000280 0001 0000 0000 0000 0000 0000 0000 0000
0000290 0031 0000 0001 0000 0002 0000 0000 0000
00002a0 0000 0000 0000 0000 006a 0000 0000 0000
00002b0 0018 0000 0000 0000 0000 0000 0000 0000
00002c0 0001 0000 0000 0000 0000 0000 0000 0000
00002d0 0039 0000 0001 0000 0030 0000 0000 0000
00002e0 0000 0000 0000 0000 0082 0000 0000 0000
00002f0 002a 0000 0000 0000 0000 0000 0000 0000
0000300 0001 0000 0000 0000 0001 0000 0000 0000
0000310 0042 0000 0001 0000 0000 0000 0000 0000
0000320 0000 0000 0000 0000 00ac 0000 0000 0000
0000330 0000 0000 0000 0000 0000 0000 0000 0000
0000340 0001 0000 0000 0000 0000 0000 0000 0000
0000350 0057 0000 0001 0000 0002 0000 0000 0000
0000360 0000 0000 0000 0000 00b0 0000 0000 0000
0000370 0038 0000 0000 0000 0000 0000 0000 0000
0000380 0008 0000 0000 0000 0000 0000 0000 0000
0000390 0052 0000 0004 0000 0000 0000 0000 0000
00003a0 0000 0000 0000 0000 05e8 0000 0000 0000
00003b0 0018 0000 0000 0000 000b 0000 0008 0000
00003c0 0008 0000 0000 0000 0018 0000 0000 0000
00003d0 0011 0000 0003 0000 0000 0000 0000 0000
00003e0 0000 0000 0000 0000 00e8 0000 0000 0000
00003f0 0061 0000 0000 0000 0000 0000 0000 0000
0000400 0001 0000 0000 0000 0000 0000 0000 0000
0000410 0001 0000 0002 0000 0000 0000 0000 0000
0000420 0000 0000 0000 0000 0490 0000 0000 0000
0000430 0108 0000 0000 0000 000c 0000 0009 0000
0000440 0008 0000 0000 0000 0018 0000 0000 0000
0000450 0009 0000 0003 0000 0000 0000 0000 0000
0000460 0000 0000 0000 0000 0598 0000 0000 0000
0000470 0020 0000 0000 0000 0000 0000 0000 0000
0000480 0001 0000 0000 0000 0000 0000 0000 0000
0000490 0000 0000 0000 0000 0000 0000 0000 0000
00004a0 0000 0000 0000 0000 0001 0000 0004 fff1
00004b0 0000 0000 0000 0000 0000 0000 0000 0000
00004c0 0000 0000 0003 0001 0000 0000 0000 0000
00004d0 0000 0000 0000 0000 0000 0000 0003 0003
00004e0 0000 0000 0000 0000 0000 0000 0000 0000
00004f0 0000 0000 0003 0004 0000 0000 0000 0000
0000500 0000 0000 0000 0000 0000 0000 0003 0005
0000510 0000 0000 0000 0000 0000 0000 0000 0000
0000520 0000 0000 0003 0007 0000 0000 0000 0000
.......

4 链接

$ gcc hello_world_main.o -o a.out

测试:

$ ./a.out 
hello world, value: 5

四、 实例分析

4.1 查看gcc版本

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)

4.2 没有选项时, 生成a.out

$ gcc hello_world_main.c

4.3 –o选项指定输出文件名

gcc -o my.out hello_world_main.c

4.4 –S产生汇编源文件

gcc  -S my.out hello_world_main.c –o hello_world_main.s

4.5 –E预处理C源文件

gcc -E hello_world_main.c –o hello_world_main.i

4.6 优化

gcc hello_world_main.c -O1

4.7 调试选项

gcc hello_world_main.c  –g

4.8 静态库、动态库链接

源码:
thread_param.c:

#include <stdio.h>
#include <string.h>
#include <pthread.h>

void *thread_func(void *arg)
{
    pthread_t tid = 0;
    long thread_number = -1;

    thread_number = (long)arg;

    tid = pthread_self();
    printf("tid:%ld, number:%ld\n", tid, thread_number);

    while (1) {
        printf("I am sub pthread, thread number:%ld\n", thread_number);
        sleep(1);
    }
}

int main(int argc, char *argv[])
{
    int ret = 0;
    long i = 0;
    pthread_t tid = 0;
    pthread_t main_tid = 0;

    for (i = 0; i < 3; i++) {
        ret = pthread_create(&tid, NULL, thread_func,  (void *)i);
    }

    while (1) {
        printf("I am main thread\n");
        sleep(1);
    }

    return 0;
}

默认编译使用动态库

$ gcc -o a.out thread_param.c –lpthread
$ ldd a.out 
	linux-vdso.so.1 =>  (0x00007fffd3bfc000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1f194d6000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1f19111000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f1f19711000)

指定使用静态库

$ gcc -o a.out --static thread_param.c –lpthread
$ ldd a.out
	not a dynamic executable

4.9 传参数给编译器 -wl

  常用的是和-Bstatic或-Bdynamic使用来指定使用静态库还是动态库
  比如有A、B两个库,并且各自都存在静态库和动态库,程序想要链接A库的静态库,B库的动态库,可以按如下方式指定:
$ gcc –o a.out test.c -Wl,-Bstatic -lA –Wl,Bdynamic -lB

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪游东戴河

你就是这个世界的唯一

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值