c语言的编译与调试
1. GCC/G++gcc和g++是GNU Compiler Collection中的编译器,分别用于编译C和C++程序。它们的编译过程主要包括四个步骤:预处理(Pre-Processing)、编译(Compiling)、汇编(Assembling)、链接(Linking)。
1.1 编译过程
[*]预处理(Pre-Processing):
gcc -E hello.c -o hello.i对hello.c文件进行预处理,生成预处理文件hello.i。
作用:扩展宏、包含头文件、处理条件编译、删除注释等。
[*]编译(Compiling):
gcc -S hello.i -o hello.s对预处理文件进行编译,生成汇编文件hello.s。
作用:将高级语言代码转换为汇编语言,便于进一步转换为机器代码。
[*]汇编(Assembling):
gcc -c hello.s -o hello.o对汇编文件进行汇编,生成目标文件hello.o。
作用:将汇编代码转换为机器代码,包含程序的二进制指令,但还未链接库函数或其他目标文件。
[*]链接(Linking):
gcc hello.o -o hello对目标文件进行链接,生成可执行文件hello。
作用:生成最终的可执行程序,可以在目标操作体系上运行。
可以一步完成所有过程:
gcc hello.c -o hello大概只生成目标文件:
gcc -c hello.c -o hello.o1.2 GCC基本使用
[*]编译单个C文件并生成可执行文件:
gcc -o outputfile sourcefile.c-o outputfile:指定输出的可执行文件名。
sourcefile.c:要编译的源文件。
[*]编译多个C文件并生成可执行文件:
gcc -o myprogram file1.c file2.c file3.c
[*]编译并生成目标文件(.o文件):
gcc -c file.c-c:仅编译,生成目标文件(object file)。
[*]指定头文件目录:
gcc -Iinclude -o myprogram src/file1.c src/file2.c-Iinclude:指定包含头文件的目录include。
详细解释:
-I 选项用于指定头文件的搜索目录。这在包含自定义头文件大概头文件不在标准目录时非常有用。
头文件(.h或.hpp文件)通常包含函数声明、宏定义、数据范例、预处理指令等。当编写一个程序时,头文件可以被多个源文件包含,以便共享这些声明和定义。
编译器默认会在一些标准目录中搜索头文件,比如 /usr/include 和 /usr/local/include。假如头文件不在这些默认目录中,编译器就无法找到它们,会报错。
使用 -I 选项可以告诉编译器在指定目录中搜索头文件。假设你的头文件在一个自定义目录中,比如 include 目录,可以使用以下下令:
gcc -Iinclude -o myprogram src/main.c这样编译器就会在 include 目录中找到头文件。以下是一个示例:
// include/myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H
void myFunction();
#endif
// src/main.c
#include "myheader.h"
#include <stdio.h>
void myFunction() {
printf("Hello from myFunction!\n");
}
int main() {
myFunction();
return 0;
}编译下令:
gcc -Iinclude -o myprogram src/main.c
[*]链接目标文件生成可执行文件:
gcc -o myprogram file1.o file2.o
1.3 GCC常用选项
[*]编译优化:
-O1、-O2、-O3:差别级别的优化。
-Os:优化生成的代码大小。
[*]调试信息:
-g:生成调试信息,用于调试程序。
[*]警告信息:
-Wall:启用所有常见的警告。
-Werror:将所有警告视为错误。
1.4 G++使用
g++用于编译C++程序,使用方法与gcc类似:
[*]编译单个C++文件并生成可执行文件:
g++ -o outputfile sourcefile.cpp
[*]编译多个C++文件并生成可执行文件:
g++ -o myprogram file1.cpp file2.cpp
[*]编译并生成目标文件(.o文件):
g++ -c file.cpp-c:仅编译,生成目标文件(object file)。
[*]指定头文件目录:
g++ -Iinclude -o myprogram src/file1.cpp src/file2.cpp-Iinclude:指定包含头文件的目录include。
[*]链接目标文件生成可执行文件:
g++ -o myprogram file1.o file2.o
2.Makefile
Makefile 是用于主动化编译和构建软件项目的工具。在大型项目中,手动编译每个文件非常繁琐,使用 Makefile 可以简化这一过程。Makefile 由一系列规则(rules)组成,每个规则包含目标(target)、依赖(dependencies)和下令(commands)。
2.1 基本结构
一个基本的 Makefile 的规则结构如下:
target: dependencies
command
[*]target:要生成的文件或目标,可以是可执行文件、目标文件或其他规则。
[*]dependencies:生成目标所依赖的文件或其他目标。
[*]command:生成目标所需执行的下令。
2.2 示例
假设有以下项目结构:
project/
├── include/
│ └── myheader.h
├── src/
│ ├── main.c
│ ├── file1.c
│ ├── file2.c
├── MakefileMakefile 内容如下:
# 指定编译器
CC = gcc
# 编译选项
CFLAGS = -Wall -g -Iinclude
# 源文件目录
SRC_DIR = src
# 所有的源文件
SRCS = $(wildcard $(SRC_DIR)/*.c)
# 生成的目标文件
OBJS = $(SRCS:.c=.o)
# 生成的可执行文件名
TARGET = myprogram
# 默认规则,生成最终的可执行文件
all: $(TARGET)
# 生成最终的可执行文件 $(TARGET),依赖所有目标文件 $(OBJS)
$(TARGET): $(OBJS)
$(CC) -o $@ $^
# 生成目标文件的规则
$(SRC_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理规则
clean:
rm -f $(OBJS) $(TARGET)
# 打印文件列表
print:
@echo "Source files: $(SRCS)"
@echo "Object files: $(OBJS)"
# 伪目标
.PHONY: all clean print2.3 变量
[*]CC:指定编译器,通常为 gcc 或 g++。
[*]CFLAGS:编译选项,如包含目录(-I)、警告(-Wall)、调试信息(-g)等。
[*]SRCS:源文件列表,由 wildcard 函数生成。
[*]OBJS:目标文件列表,由源文件列表通过模式替换生成。
[*]TARGET:最终生成的可执行文件名。
2.4 规则说明
<ul>all 规则:
all: $(TARGET)默认规则,生成目标文件 $(TARGET)。
$(TARGET) 规则:
$(TARGET): $(OBJS)
$(CC) -o $@ $^生成最终的可执行文件 $(TARGET),依赖所有目标文件 $(OBJS)。
模式规则:
$(SRC_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
通用规则,将 .c 文件编译为 .o 文件。$
页:
[1]