Linux C 和Windows C
- 标准C,ANSI-C
- Windows C
- Linux C
GCC 编译器
GNU编译器套件(GNU Compiler Collection) GNU:是GNU is Not Unix的递归缩写,即类Unix操作系统 Linux:Linux Is Not UniX PNG:PNG’s Not GIF RPM:RPM Package Manager
![](
GCC 安装
mac一般自带gcc,通过gcc --version
,查看gcc版本;
CentOS 安装:yum install gcc 默认已安装;
Ubuntu 安装:apt-get install gcc 默认已安装;
GCC常用命令
命令参数 | 说明 |
---|---|
–help | 帮助信息 |
-save-temps | 不删除中间文件 |
-Werror | 所有警告当做是错误 |
-w | 不显示警告 |
-m32/-m64 | 生成32/64位程序 |
-D | 追加宏定义 |
-L | 追加库文件目录 |
-l | 追加库文件 |
-I | 追加头文件目录 |
-include | 追加头文件 |
查看完整信息,采用命令man gcc
hello gcc
编写hello world程序如下:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello world\n");
return 0;
}
分步编译如下(其中输出扩展名可以自定义):
gcc -E hello.c -o hello.i #预编译,输出hello.i
gcc -S hello.i -o hello.s #编译,生成hello.s
gcc -c hello.s -o hello.o #汇编,生成hello.o
gcc hello.o -o hello #链接,生成可执行程序hello
./hello # 执行可执行程序hello
这几步等价于
gcc hello.c -o hello
;
如果没有指定-o参数,默认输出为a.out
编译32位程序
gcc -m32 hello.c -o hello32
;
编译64位程序
gcc -m64 hello.c -o hello64
;
查看可执行程序是32或64位命令:
personal:projects apple$ file hello
hello: Mach-O 64-bit executable x86_64
personal:projects apple$ file hello32
hello32: Mach-O executable i386
personal:projects apple$ file hello64
hello64: Mach-O 64-bit executable x86_64
gcc默认按当前系统是32还是64位编译cx,查看系统位数的命令是:uname
personal:projects apple$ uname -a
Darwin personal.local 16.1.0 Darwin Kernel Version 16.1.0: Thu Oct 13 21:26:57 PDT 2016; root:xnu-3789.21.3~60/RELEASE_X86_64 x86_64
多文件编译
多文件编译遵循一条原则:
- 头文件,无需在gcc中指定,因此头文件的个数不影响编译结果;
- 源文件:gcc a.c,b.c -o 源文件顺序可调。 提高编译速度的技巧,假设有多个文件a.c,b.c,可分开编译到汇编这一步,最后链接时再一块编译,以后a或b有变化时,无需全量编译,只编译有修改的源文件,再执行链接就可以了。
gcc -c a.c -o a.o # 执行到汇编这步
gcc -c b.c -o b.o
gcc a.o b.o -o hello #链接生成可执行程序
GDB调试
GDB简介
GDB:GNU DeBuger,与GCC配套的调试工具 ; man gdb 查看帮助手册; mac上gdb安装和使用参考: https://blog.csdn.net/github_33873969/article/details/78511733
GDB 常用命令
要想使用gdb调试,需要在使用gcc编译时指定-g参数: 在目标文件加入源代码 gcc -g xxx.c -o xxx
gdb xxx 开始调试,进入gdb控制台
(gdb) list 或者 l 列出所有代码
(gdb) run 或者 r 运行程序
(gdb) start 开始调试
(gdb) quit 或者 q 退出调试
(gdb) next 或者 n 运行下一行,仅在当前函数
(gdb) step 或者 s 运行下一行,可进入函数
(gdb) print 或者 p 变量名 打印变量当前值
(gdb) set var i=3 局部变量设置
(gdb) info 或者 i 查看信息 locals 查看当前变量
(gdb) break 或者 b 设置断点,接行号或函数
(gdb) continue 或者 c 继续运行,直到下一个断点
(gdb) info 或者i breakpoints 列出断点
(gdb) delete或者d 删除断点
静态链接库和动态链接库
静态库和动态库的定义和特点可以参考:
https://www.cnblogs.com/king-lps/p/7757919.html
静态链接库
静态库是二进制文件,可链接为可执行文件,以提供功能函数为主要目的,可被其他库或可执行文件调用,且与他们无依赖关系。在Windows系统扩展名为.lib,linux和mac系统扩展名为.a;
静态链接库编译
静态链接库编译和打包流程如下:
- step 1,源文件编译到汇编的目标文件,
gcc -c xxx.c -o xxx.o
; - step 2,有两种方式:
ar rs libxxx.a xxx.o
,把目标文件xxx.o打包成静态库文件libxxx.a;ar r libxxx.a xxx.o ranlib libxxx.a
,使用ranlib来对静态库的符号索引表进行更新.
- step 3,
gcc main.c -L. -lxxx -o main
,使用静态链接库编译可执行程序,-L.指添加当前目录为库目录,-lxxx指添加名为xxx的库。
代码实战
新建代码文件如下:
#test1.h
int sum(int a,int b);
# test1.c
#include "test1.h"
int sum(int a,int b){
return a+b;
}
# test2.h
int sub(int a,int b);
# test2.c
#include "test2.h"
int sub(int a,int b){
return a-b;
}
#demo.c
#include <stdio.h>
#include "test1.h"
#include "test2.h"
int main(){
int x = 5;
int y = 3;
int ret = sum(x,y);
printf("%d+%d=%d\n",x,y,sum(x,y));
printf("%d-%d=%d\n",x,y,sub(x,y));
return 0;
}
执行命令如下:
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
demo.c test1.c test1.h test2.c test2.h
guangjiepengdeMacBook-Pro:demo guangjie.peng$ gcc -c test1.c -o test1.o
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
demo.c test1.c test1.h test1.o test2.c test2.h
guangjiepengdeMacBook-Pro:demo guangjie.peng$ gcc -c test2.c -o test2.o
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
demo.c test1.c test1.h test1.o test2.c test2.h test2.o
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ar rs libcalc.a test1.o test2.o
ar: creating archive libcalc.a
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
demo.c test1.c test1.o test2.h
libcalc.a test1.h test2.c test2.o
guangjiepengdeMacBook-Pro:demo guangjie.peng$ gcc demo.c -L. -lcalc -o demo
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
demo libcalc.a test1.h test2.c test2.o
demo.c test1.c test1.o test2.h
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ./demo
5+3=8
5-3=2
可执行程序不依赖静态库验证:
guangjiepengdeMacBook-Pro:demo guangjie.peng$ mv demo ../demo2
guangjiepengdeMacBook-Pro:demo guangjie.peng$ cd ..
guangjiepengdeMacBook-Pro:Downloads guangjie.peng$ ./demo2
5+3=8
5-3=2
ar类似命令tar,也可以解压静态库:
guangjiepengdeMacBook-Pro:demo guangjie.peng$ rm -rf test1.o test2.o
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
__.SYMDEF SORTED test1.c test2.h
demo.c test1.h
libcalc.a test2.c
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ar -x libcalc.a
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
__.SYMDEF SORTED test1.c test2.c
demo.c test1.h test2.h
libcalc.a test1.o test2.o
使用clion创建静态库
-
创建:在创建project时可以选择可执行过程还是library过程,以及选择静态库和动态库。demo工程如下:
-
Build,Run->Build,会在cmake-build-debug目录生成.a静态库文件;
使用Clion调用静态库
-
拷贝创建好的静态库libhellolibrary.a和library.h到clion根目录;
#library.h #ifndef HELLOLIBRARY_LIBRARY_H #define HELLOLIBRARY_LIBRARY_H void hello(); #endif #library.cpp #include "library.h" #include <iostream> void hello() { std::cout << "Hello, Library!" << std::endl; }
-
打开clion工程的CMakeLists.txt,添加要链接的静态库,如下:
cmake_minimum_required(VERSION 3.10)
project(clion)
set(CMAKE_CXX_STANDARD 11)
set(LIB_DIR /Users/guangjie.peng/development/clion)#定义变量
link_libraries(${LIB_DIR}/libhellolibrary.a)#指定要链接的静态库
-
在clion中调用静态库的方法:
void testStaticLibrary(){ hello(); }
动态链接库
动态链接库打包过程
动态库之间以及与调用程序之间存在依赖关系.
- step 1,
gcc -fPIC -c xxx.c -o xxx.o
,编译目标文件时增加-fPIC 参数; - step 2,
gcc -shared xxx.o -o libxxx.so
,打包so库; - step 3,
gcc main.c -L. -lxxx -o main
,与可执行文件链接。 - step 4,mac上可直接执行:
./main
,Linux上需要把so库拷贝到/usr/lib/目录,然后执行ldconfig命令;
代码实战
复用静态库demo代码,执行命令如下:
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
__.SYMDEF SORTED demo.c test1.c test1.h test2.c test2.h
guangjiepengdeMacBook-Pro:demo guangjie.peng$ gcc -fPIC -c test1.c test2.c
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
__.SYMDEF SORTED test1.c test1.o test2.h
demo.c test1.h test2.c test2.o
guangjiepengdeMacBook-Pro:demo guangjie.peng$ gcc -shared test1.o test2.o -o libcalc.so
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
__.SYMDEF SORTED libcalc.so test1.h test2.c test2.o
demo.c test1.c test1.o test2.h
guangjiepengdeMacBook-Pro:demo guangjie.peng$ gcc demo.c -L. -lcalc -o demos
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ls
__.SYMDEF SORTED demos test1.c test1.o test2.h
demo.c libcalc.so test1.h test2.c test2.o
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ./demos
5+3=8
5-3=2
尝试删除so库,看demo是否能正常运行:
guangjiepengdeMacBook-Pro:demo guangjie.peng$ ./demos
dyld: Library not loaded: libcalc.so
Referenced from: /Users/guangjie.peng/Downloads/demo/./demos
Reason: image not found
Trace/BPT trap: 5
Clion创建动态链接库验证
流程同静态库,选择shared library就可以了;
调用动态链接库
- step 1,同样拷贝so和头文件到调用工程根目录下;
- step 2,编辑CMakeLists.txt文件,加入如下代码:
target_link_libraries(clion /Users/guangjie.peng/development/clion/libhellolibrary.so)