gcc学习笔记
1:第一个程序 : hello world
#include <stdio.h>
int main(void)
{
printf("Hello , world ! \n");
return 0;
}
编译: gcc -Wall hello.c -o hello
2:调试错误 : debug.c
#include <stdio.h>
int main(void)
{
printf("Two plus two is %f \n", 4);
return 0;
}
编译: gcc -Wall hello.c -o hello
错误 1: 乱码 解决: export LANG=c
然后可以提示代码中的错误
3:拆分程序
将hello.c拆分成3个文件
hello1.c 自定义函数定义
hello.h 自定义函数声名文件
main.c 主文件
hello1.c
#include <stdio.h>
void hello(const char* string)
{
printf(string);
}
hello.h
#include <stdio.h>
void hello(const char* string);
main.c
#include <stdio.h>
#include "hello.h"
int main(void)
{
hello("hello world \n");
return 0;
}
编译多个文件 : gcc -Wall main.c hello1.c -o newhello
4 :Verbose Compilation
主要用于调试程序,显示程序编译的详细信息
格式 : gcc -v -Wall hello.c -o hello
5: 独立编译
每个.c文件独立编译成一个.o(windows中obj文件),最后通过链接器(linker)成为一个可执行文件。只用重新编译修改的文件。
格式: gcc -Wall -c main.c gcc -Wall -c hello1.c
此时会生成目标文件(与源文件同名,扩展名.o)
链接器: gcc main.o hello1.o -o bbk
6:Make的作用
只编译修改过的文件生成.o文件,对于没有更新过的源文件则不重新编译
7:Linking With External Libraries
系统库不需要显式声明
例:
#include <math.h>
#include <stdio.h>
int main(void)
{
double m;
scanf("%L",&m);
double x = sqrt(m);
printf("The square root of 2.0 is %f \n", x);
return 0;
}
老版本的编译器需要显式声明:
gcc -Wall main.c /usr/lib/libm.a -o calc
同: gcc -Wall main.c -lm -o calc
注: -lNAME 等价于连接库文件 libNAME.a (标准目录下,不是当前目录)
8: Common Problem In compiling
header files or library file is (头文件和库文件的默认路径):
/usr/local/include/
/usr/include/
/usr/local/lib g
/usr/lib
调用用户的头文件
1: gcc -Wall -I/usr/myheaerdir -L./ -lmy.a (推荐方法) -I 设置头文件的路径,-L库文件目录
2: 通过shell设置环境变量 ,变量名: C_INCLUDE_PATH LIBRARY_PATH
3:修改环境变量
9:Create a Library with ar
通过ar 命令将一堆的目标文件(.o文件)连接成一个库文件(.a文件),然后主文件连接此库文件
格式: ar cr libNAME.a file1.o file2.o .... filen.o
根据库文件,查看连接的目标文件
格式: ar t libmy.a
例:
mylib.h
int func1(int x, int y);
void func2(int x);
fun1.c
#include "mylib.h"
int func1(int x, int y)
{
return (x+y);
}
fun2.c
#include<stdio.h>
#include "mylib.h"
void func2(int x)
{
printf("the int is %d\n", $x);
}
maina.c
#include<stdio.h>
#include "mylib.h"
int main(void)
{
int i ;
i = func1(1,2);
func2(i);
return 0;
}
操作顺序:
1:gcc -Wall -c fun1.c //生成目标文件
2:gcc -Wall -c fun2.c
3:ar cr libhello.a fun1.o fun2.o //将两个目标文件生成1个库文件libhello.a
4:gcc -Wall maina.c libhello.a -o hello (注意maina.c放在库文件的前面,遵循先调用后定义的原则 ,将maina.c编译成目标文件后,用3个目标文件编译可忽略次序问题
)
同:gcc -Wall main.c -L. -lhello -o h3 ("L"设置库文件的韦当前目录,"l"库文件名)
设置系统的环境变量:
1:查看系统的环境变量 env | grep LIB
2:设置系统的全局变量 export LIBRARY_PATH=/usr/local/gcc:$LIBRARY_PATH
调整程序目录为
include目录 mylib.h
lib目录 libhello.a
mina.c
编译: gcc -Wall maina.c -Iinclude -Llib -lhello -o h4
查看库文件由哪些目标文件合成:
ar t libhello.a
研究Apache的源码
10:Shared Vs Static Library (动态库、静态库)
动态库,windows下dll文件 linux下so文件
可执行文件执行时,先加载动态库到内存,动态库可被多个可执行文件共离
将动态库放到系统的标准目录/usr/local/lib /usr/lib
设置系统变量 LB_LIBRARY_PATH
11:C的版本
标准C、Gcc支持的特殊方式
例:ansi.c
#include <stdio.h>
int main(void)
{
const char asm[] = '6705';
printf("the string asm is '%s'\n", asm);
return 0;
}
gcc -Wall ansi.c -o an
直接编译会报错,原因:asm不是标准C的关键词,是gcc支持C 的关键字
修正: gcc - Wall -ansi ansi.c -o an
例2:pi.c
#include <math.h>
#include <stdio.h>
int main(void)
{
printf("the value of pi is %f \n", M_PI);
return 0;
}
gcc - Wall -ansi pi.c -o pi c
将会报错,原因:宏M_PI 在标准C中没有定义,Gcc支持
gcc -Wall pi.c -o pi
解决办法:编译时,调用Gnu的宏定义
gcc -Wall -ansi -D_GNU_SOURCE pi.c -o pp
例3:严格C标准 v.c
#include <stdio.h>
int main(int argc, char* argv[])
{
int i, n = argc;
double x[n];
for(i = 0; i < n ; i++)
{
x[i] = i;
}
printf("result is %l \n", x);
return 0;
}
gcc -Wall -ansi -pedantic v.c -o v // 两个选项,强制按照C标准
以上会报错,标准C不支持可变长的数组
gcc -Wall v.c -o v
-Wall的相关选项
1:注释问题,嵌套注释的错误 -Wcomment
解决方法:外层注释用宏定义
#if 0
/* 被注释掉的内容 */
#endif
2: -Wunused
声明但未使用的变量
12: Using the Preprocessor 预处理(替换代码中的宏定义等操作)
例:
dtest.c
#include <stdio.h>
int main(void)
{
#ifdef TEST
printf("Test mode\n");
#endif
printf("Running...\n");
return 0;
}
gcc -Wall -DTEST=456 dtest.c -o dt //编译时定义一个宏,默认值为1
查看系统的宏定义: cpp -dM /dev/null
-D 编译时定义宏
-E 只预处理程序,不编译 (只替换源文件中的include和宏定义)
-save-temp 编译时,保存预处理后的结果(.i文件和.s文件) .i => .s =>.o
例:
hello1.c
#include <stdio.h>
int main(void)
{
printf("Hello , world ! \n");
return 0;
}
gcc -Wall -c -save-temps hello1.c
13: Compiling for Debugging
可执行文件中只包含机器码,不利于调试。调试模式可保存行号等信息
当程序意外终止,将产生一堆'core'文件 (ulimit -c unlimited 设置不限制dump文件大小,默认不允许产生dump文件)
用gdb对core进行调试
-g 选项以调试模式来编译源代码(将行号等信息保存在可执行文件中)
例:null.
#include <stdio.h>
int a (int *p);
int main(void)
{
int* p = 0;
return a(p);
}
int a(int *p)
{
int y = *p;
return y;
}
程序bug:指针p指针地址为0的内存空间(系统核心的地址),将报错
调试: gcc -Wall -g null.c (-g选项 用于调试用,将源码中的相关信息保存在最终的可执行文件中)
执行程序: ./a.out (提示错误,程序 core dumped; 同时产生错误日志core.)
将产生core文件,通过gdb可调试此出错的文件
命令:gdb a.out core.989 (此时可查看到相关的错误信息)
gdb中可用的简单操作:
print p (打印变量)
backtrace (返回上一步的调用 )
14: Compiling with Optimization
gcc会根据不同的CPU自动优化代码;
Source-level Optimization
源码层次的优化
1:CSE (公共子进程优化)
例:
x = cos(v) * (1 + sin(u/2)) + sin(w) * (1 - sin(u/2))
优化为:
t = sin(u/2);
x = cos(v) * (1 + t) +sin(w) * (1 - t)
2: Function Inlining (FL)
对于频繁调用的函数,执行入栈、出栈操作比较频繁,效率低,可将函数声明为inling function
例:
inling double sq(double x)
{
return (x * x);
}
sum = 0.0;
for(i = 0; i< 1000000; i++)
{
sum += sq(i + 0.5); //调用函数过程:将当前地址入栈,转到函数地址,执行完函数再出栈
}
人为优化:
t = i + 0.5;
sum += t *t;
注:当优化开头打开时,会自动对代码进行优化;或者人为的知道函数调用频率高,可将函数声明为inline函数;
15: Loop Unrolling (speed-space tradeoff)
每循环一次,都要判断是否结束,增加开销;
例:
for(i = 0 ; i< 8; i++)
{
y[i] = i;
}
简单优化:
y[0] = 0;
y[1] = 1;
y[2] = 2;
y[3] = 3;
y[4] = 4;
y[5] = 5;
y[6] = 6;
y[7] = 7;
16:Scheduling
并行执行 指令,编译执行时间长,不会增大可执行文件大小及内存
17:Optimization level
优化等级, 指令: -oLEVEL // level is a number from 0 to 3
-o0 用于debug
-o2 用于生产环境
test.c
#include <stdio.h>
double powern(double d, unsigned n)
{
double x = 1.0;
unsigned j;
for(j=0; j<n; j++)
x *=d;
return x;
}
int main(void)
{
double sum = 0.0;
unsigned i;
for(i=1; i< 100000000; i++)
{
sum += powern(i, i%5);
}
printf("sum = %g \n", sum);
return 0;
}
gcc -Wall -o0 test.c -o test0
查看执行时间 time ./test0
gcc -Wall -o3 -funroll-loops test.c -o test4 //for循环优化
Gcc常用总结:
参数
-I (大写i) 头文件路径
-L 库文件路径
-l 库文件名称 (-lmy 等价 libmy.a)
-o 生成可执行文件
-c 编译单个文件为目标文件
-W 错误级别
-v 显示编译过程中的详细信息
将目标文件生成库文件
ar cr libabc.a file1.o file2.o file3.o
查看库文件包含的目标文件
ar t libabc.a
gcc学习笔记的更多相关文章
- Centos7升级gcc学习笔记
概述 最近在学习<深入应用C++11-代码与优化与工程级应用>,我的gcc版本是gcc-4.8.5是支持C++11的,但是我在作者的github上看了一些C++例子,其中有些是C++14的 ...
- Centos7升级gcc学习笔记 gcc 4.8.5 -> gcc 5.4.0
摘自:https://www.cnblogs.com/highway-9/p/5628852.html 一.安装开发必备环境: yum groupinstall "Development T ...
- 【嵌入式开发】gcc 学习笔记(一) - 编译C程序 及 编译过程
一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...
- gcc 学习笔记(一) - 编译C程序 及 编译过程
一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...
- (转)gcc学习笔记
1.gcc -Wall hello.c -o hello //编译源文件,显示警告信息 2../a.out //运行程序 3.gcc -Wall calc.c /usr/lib/libm.a -o ...
- GCC/G++ 学习笔记
本文是<An introduction to GCC>的学习笔记,记录使用GCC/G++主要的实用技巧,本文讲述的知识基本上摘自本书,附带自己的一些体验.如果想详细查看本书,请戳这里. 一 ...
- Python学习笔记—Python基础1 介绍、发展史、安装、基本语法
第一周学习笔记: 一.Python介绍 1.Python的创始人为吉多·范罗苏姆.1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言 ...
- Caffe学习笔记2--Ubuntu 14.04 64bit 安装Caffe(GPU版本)
0.检查配置 1. VMWare上运行的Ubuntu,并不能支持真实的GPU(除了特定版本的VMWare和特定的GPU,要求条件严格,所以我在VMWare上搭建好了Caffe环境后,又重新在Windo ...
- 驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址
驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址 最近重新看了乾龙_Heron的<ARM 上电启动及 Uboot 代码分析>(下简称<代码分析>) ...
随机推荐
- U3D使anim,unity,prefab文件不显示乱码
Edit-Project Setting-Editor-Asset Serialization-mode Force Text
- netstat命令详解
它主要的用法和详解! (netstat -na 命令),本文主要是说Linux下的netstat工具,然后详细说明一下各种网络连接状态. netstat -nat |awk ‘{print $}’|s ...
- [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序实现继承
这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第十一篇:为ASP.NET MVC应用程 ...
- Analyzer报表结果行
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- 解决 Cannot find OpenSSL's <evp.h>
yum install openssl openssl-devel ln -s /usr/lib64/libssl.so /usr/lib/
- 课时8—弹窗modal
首先弹窗的实现效果如下: 主要实现的代码如下: CSS: .header,.footer,.wrap-page{ position:absolute; left:; right:; backgroun ...
- 如何在MapControl界面添加双击事件实现标绘及符号样式更改
private void axMapControl1_OnDoubleClick(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnDo ...
- JQ二级菜单练习之一~~~
<div class="nav"> <ul> <li><a href="#">首页</a> < ...
- row_number() OVER(PARTITION BY)函数介绍
OVER(PARTITION BY)函数介绍 开窗函数 Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个 ...
- 解决ssh链接服务器超时自动断开的问题
为了安全性:ssh默认的连接超时时间很短:经常就是发个呆就断开了:事实上是可以修改超时时间的. 示例环境: 服务器:centos6.5 1:[root@iZ28qa8jt4uZ /]cp /etc/s ...