16.C语言GCC编译与条件编译

本文介绍了GCC,从其历史发展、支持的编程语言,到编译过程(预处理、编译、汇编、链接),并详细讲解了常用的编译选项,以及如何通过条件编译控制代码编译。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GCC简介

  1. GCC 原名为 GNU C 语言编译器(GNU C Compiler),只能处理 C 语言。但其很快扩展,变得可处理 C++,后来又扩展为能够支持更多编程语言,如 Fortran、Pascal、Objective -C、Java、Ada、Go 以及各类处理器架构上的汇编语言等,所以改名 GNU 编译器套件(GNU Compiler Collection)。
  2. GCC(特别是其中的 C 语言编译器)也常被认为是跨平台编译器的事实标准。
  3. GCC 提供了 30 多条警告信息和 3 个警告级别,使用它们有助于增强程序的稳定性和可移植性。
  4. GCC 还对标准的 C/C++ 语言进行了大量的扩展,提高了程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量。

GCC编译过程

GCC编译步骤

  1. 预处理(Pre-Processing);
  2. 编译(Compiling),检查语法错误;
  3. 汇编(Assembling),生成二进制文件,还不能执行;
  4. 链接(Linking),链接库文件。

在这里插入图片描述

GCC常用选项

  1. -c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
  2. -o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
  3. -g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。
  4. -O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。
  5. -O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
  6. -I dirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。(gcc main.c file.c -I inlcude)
  7. -L dirname,将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在链接过程中使用的参数。(gcc test.c -o test -lpthread 链接库文件) (gcc test.c -o test -L/home/linux -lpthread 指定某个目录下的库文件 )
#include <stdio.h>

int fun(){
	return 1;
}

int a = 5;
int main(int argc, const char *argv[])
{
	static int c;
	fun();	
	return 0;
}

gcc -E demo01.c -o demo01.i

demo01.i文件

# 1 "demo01.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "demo01.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 375 "/usr/include/features.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 392 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 393 "/usr/include/sys/cdefs.h" 2 3 4
# 376 "/usr/include/features.h" 2 3 4
# 399 "/usr/include/features.h" 3 4
# 1 "/usr/include/gnu/stubs.h" 1 3 4
# 10 "/usr/include/gnu/stubs.h" 3 4
# 1 "/usr/include/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/gnu/stubs.h" 2 3 4
# 400 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4





# 1 "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h" 1 3 4
# 212 "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/stdio.h" 2 3 4

# 1 "/usr/include/bits/types.h" 1 3 4
# 27 "/usr/include/bits/types.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 28 "/usr/include/bits/types.h" 2 3 4


typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;


typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;

typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;

#........................

# 943 "/usr/include/stdio.h" 3 4

# 2 "demo01.c" 2

int fun(){
 return 1;
}

int a = 5;
int main(int argc, const char *argv[])
{
 static int c;
 fun();
 return 0;
}

gcc -S demo01.i -o demo01.s

demo01.s文件

	.file	"demo01.c"
	.text
	.globl	fun
	.type	fun, @function
fun:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$1, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	fun, .-fun
	.globl	a
	.data
	.align 4
	.type	a, @object
	.size	a, 4
a:
	.long	5
	.text
	.globl	main
	.type	main, @function
main:
.LFB1:
	.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	$0, %eax
	call	fun
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main
	.local	c.2183
	.comm	c.2183,4,4
	.ident	"GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
	.section	.note.GNU-stack,"",@progbits

gcc -c demo01.s -o demo01.o

demo01.o文件是二进制文件

gcc demo01.o -o demo01

demo01文件:有权限可执行文件

条件编译

一般情况下,C语言源程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译,此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译(conditional compile)。

#include <stdio.h>


int main(int argc, const char *argv[])
{
	#ifdef A
		#define N 10
		printf("%d\r\n",N);
	#endif
	#ifdef B
		#define M 20
		printf("%d\r\n",M);
	#endif
		
	#if VALUE
		printf("=============\r\n");
	#else
		printf("*************\r\n");
	#endif
	return 0;
}

使用-D编译:gcc demo01.c -D A -D VALUE=1

来选择需要编译那部分的代码块。

在创建h文件时可以做到去重复定义:

database.h

#ifndef _DATABASE_H
#define _DATABASE_H
//.....
#endif
//这里要隔一行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值