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学习笔记的更多相关文章

  1. Centos7升级gcc学习笔记

    概述 最近在学习<深入应用C++11-代码与优化与工程级应用>,我的gcc版本是gcc-4.8.5是支持C++11的,但是我在作者的github上看了一些C++例子,其中有些是C++14的 ...

  2. Centos7升级gcc学习笔记 gcc 4.8.5 -> gcc 5.4.0

    摘自:https://www.cnblogs.com/highway-9/p/5628852.html 一.安装开发必备环境: yum groupinstall "Development T ...

  3. 【嵌入式开发】gcc 学习笔记(一) - 编译C程序 及 编译过程

    一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...

  4. gcc 学习笔记(一) - 编译C程序 及 编译过程

    一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...

  5. (转)gcc学习笔记

    1.gcc -Wall hello.c -o hello //编译源文件,显示警告信息 2../a.out   //运行程序 3.gcc -Wall calc.c /usr/lib/libm.a -o ...

  6. GCC/G++ 学习笔记

    本文是<An introduction to GCC>的学习笔记,记录使用GCC/G++主要的实用技巧,本文讲述的知识基本上摘自本书,附带自己的一些体验.如果想详细查看本书,请戳这里. 一 ...

  7. Python学习笔记—Python基础1 介绍、发展史、安装、基本语法

    第一周学习笔记: 一.Python介绍      1.Python的创始人为吉多·范罗苏姆.1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言 ...

  8. Caffe学习笔记2--Ubuntu 14.04 64bit 安装Caffe(GPU版本)

    0.检查配置 1. VMWare上运行的Ubuntu,并不能支持真实的GPU(除了特定版本的VMWare和特定的GPU,要求条件严格,所以我在VMWare上搭建好了Caffe环境后,又重新在Windo ...

  9. 驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址

    驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址 最近重新看了乾龙_Heron的<ARM 上电启动及 Uboot 代码分析>(下简称<代码分析>) ...

随机推荐

  1. Underscore.js 初探

    一. 简介   Underscore 这个单词的意思是“下划线”.   Underscore.js 是一个 JavaScript 工具库,提供了一整套的辅助方法供你使用.   Think that - ...

  2. JAVA线程锁-读写锁应用,简单的缓存系统

    在JAVA1.5版本以后,JAVA API中提供了ReadWriteLock,此类是一个接口,在它的实现类中ReentrantReadWriteLock中有这样一段代码 class CachedDat ...

  3. 基于ASP.NET MVC定时执行任务调度

    相对FluentScheduler实现定时调度任务的使用简单,配置少的特点,Quartz.Net则配置稍微复杂一些.下面我们就接合一个 ASP.NET MVC网站应用程序的定时执行任务调试的小实例来了 ...

  4. 自建数据源(RSO2)、及数据源增强

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  5. C#类遍历

    foreach语句的基本用法大家都应该知道,就是对对象进行遍历,取出相应的属性名称或属性值.Foreach(for)用法在js中使用很简单,基本如下: var objA={name:'mayday', ...

  6. console打印数组object具体内容

    例如 var data=[ {}, {}, {} ] 需要打印出以上data中每个{}内容,可以使用如下方式: for(var i=0;i<data.length;i++) { var a = ...

  7. javascript 函数声明和函数表达式的区别(学习笔记)

    javascript中声明函数的方法有两种:函数声明式和函数表达式. 区别如下: 1).以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的. 2).以函数声明的方法定义的函数,函 ...

  8. Android SDK Manager 更新不了文件 提示https://dl-ssl.google.com refused

    sdk manager无法自动更新,总在提示超时!!!SDK更新时的“https://dl-ssl.google.com refused”错误 解决方法: 在Android SDK Manager-& ...

  9. [css]需警惕CSS3属性的书写顺序

    转载张鑫旭:http://www.zhangxinxu.com/wordpress/2010/09/%E9%9C%80%E8%AD%A6%E6%83%95css3%E5%B1%9E%E6%80%A7% ...

  10. Xshell 登录 AWS CentOS 出现“所选择的用户秘钥未在远程主机上注册“,最终解决办法!

     其实就是 登录用户名错了,是 root,不是centos 也不是 ec2-user !  Xshell 连接配置界面如下 最重要是 登录授权配置 最后,登录成功! 就这么简单