1> 编译源文件生成目标文件
gcc -c file1.c [file2.c ...] //单文件注意文件名
2> 使用ar命令打包
ar -crv libxxx.a *.o //库文件必须以lib开头,后缀为.a
-c 创建
-v 显示过程
-r 插入文件
3> 使用静态库
方式一:将库文件当普通.o文件一样对待
gcc -o [execfilename] *.o libxxx.a
方式二:指定库文件路径与名称
gcc -o [execfilename] *.o [-L.] -lxxx
其中
-L:指定库文件路径(使用系统库文件可不指定)
-l:指定库文件名(去掉lib前缀与.a后缀)
4> 查看库文件、目标文件、可执行文件包含的函数
nm filename
1> 生成与位置无关的.o文件
gcc -fPIC -c *.c -Iinclude
2> 生成.so文件
gcc -shared -o libxxx.so *.o
3> 使用
方法一
gcc main.c libxxx.so -o app
方法二
gcc main.c -L. -l xxx -o app
使用ldd 可执行文件名查看依赖的共享库
解决方案
1.将自己的库文件放到/lib或/lib64里面(不建议)
2.配置LD_LIBRARY_PATH变量
export LD_LIBRARY_PATH = ./lib
2(或).修改配置文件
vi ~/.bashrc
export LD_LIBRARY_PATH=/path/to/yourlibfile
a) 条件编译有三种形式:
第一种:
#if ONE
语句一
语句二
#elif TWO
语句
#else
语句
#endif
#if 0/1
这里的代码可以通过#if后面的值的真假来判断是否启用
#end if
第二种:
#ifndef 宏一
#elif !defined 宏二
#else
#endif
第三种
#ifdef 宏一
#elif defined 宏二
#else
#endif
a) assert断言宏执行原理:首先判断宏参数的表达式的真假,如果为假,就向标准错误输出(s’tderr)一条错误消息,消息内容包括:在哪个文件,第几行,哪个函数,断言参数所表示的表达式失败了,紧着就会调用系统函数abort,来终止程序执行,如果判断表达式为真,程序就会继续向下执行。
b) assert断言宏 用来帮助程序员在代码调试阶段找到程序中的BUG,一旦程序调试通过,就应该关闭这个断言宏。在将来某时需要继续调试代码,需要再次启用下面的断言宏。
a)指针:就是一个地址,指针变量:保存指针(地址)的变量。
b)作用:1,共享数据,2,避免副本。
c) C语言中函数参数的传递都是值传递,传递其实是实参值的副本。
d) int a=10,*p=&a;
指针变量的值:&a或p
指针变量指向的变量值:10,a,*p
指针变量的类型:int *
指针变量指向变量的类型:int
d) 二级指针:指向指针变量的指针。**pp //二级指针,从这个声明中我们可以知道:pp指针变量本身的类型是int ** pp指向的变量类型是 int *.
e) 指针变量:以地址为指的变量。指针变量的类型:声明中去掉变量名剩下的部分,就是指针变量的类型。指针变量指向的变量的类型:声明中去掉变量名和前面的一个*号,剩下的一部分就是。
f) 数组名只要出现在表达式中,类型就是指向其中首个元素的指针类型。Int a[3]; int b=*(a+1); //a的类型是:int * int a2[2][3]; int c=*(*(a2+1)+2); //a2的类型为int(*)[3] c=*(a2[1]+2);//a2[1]的类型是:int*
a)数组:存放一组数据类型的集合。
b)数组名表示数组的起始地址,也就是说数组名就是一个地址,指向数组中的第0个元素。
c) int arr[5]; //数组arr类型是:int [5],数组中的元素类型是;int
d)arr[5]={1,2,3,4,5};//错误 数组整体赋值只能在定义的同时,如果在定义之后赋值需要逐个给数组赋值。
e)二维数组:arr[2][5];
arr二维数组本身的类型:char[2][5];
arr数组中的每个元素(其实就两个元素:arr[0]和arr[1])的类型是:char[5];
arr[0]和arr[1]里存放的元素类型是:char
g) 数组名只要出现在表达式中就表示数组的首地址。
h) 字符数组:char s[]={‘w’,’o’,’r’,’l’,’d’}; char *ps; ps=ps+2;//指向s[2]这个元素
Char *p[5];//定义指针数组 char (*parr)[5];//定义数组指针;
Parr=&s; printf(“%p”,*parr);//打印字符数组地址printf(“%c”,*(*parr+1)); //输出内容为字符o。
Char *s[]={“world,”linux}; //二维字符数组,s中的元素类型是char*s在表达式中类型是指向其中首元素的指针类型,所以s的类型是char **。
printf(“s数组元素的个数为:%lu\n”,sizeof(s)/sizeof(char *); //s数组元素的个数为:2.
Char *p1=s[1]+2; //定义p1指针指向数组中的第一个元素中的第二个元素
Printf(“%c\n,*p1); //n printf(“%c\n”,*(p1-5)); //l
Printf(“%s\n”,s[1]); //linux printf(“%s\n”,*(s+1));// linux
Char **p2=s+1; //定义p2指针,指向数组中的第一个元素
Printf(“p2:%s\n”,*p2); //linux printf(“p2:%s\n”,*p2+2); //nux
Printf(“p2:%c\n”,*(*p2+2)); //n
a)内存:段式架构 从内存地址开始到高地址
1》代码段:函数和只读数据.
.text:函数
.rodata:只读数据。
2》数据段:
.data:存放已经被初始化过的变量。
.bss:存放未被初始化的变量
3》堆区(heap):存放程序运行过程中动态申请变量的内存
4》栈区(stack):存放函数定义的非静态变量
//以上四个段,是用户空间段
5》内核段:内核空间段