4.函数 1).函数的使用规范: 第一:遵循一定格式。函数的返回类型、函数名、参数列表等。 第二:一个函数只做一件事:函数不能太长也不宜太短,原则是一个函数只做一件事情。 第三:传参不宜过多:在ARM体系下,传参不宜超过4个。如果传参确实需要多则考虑结构体打包 第四:尽量少碰全局变量:函数最好用传参返回值来和外部交换数据,不要用全局变量。 2).函数库: 最初是几个大神把一些函数源码放在一起,组成了函数库。 然后在商业上把函数库源码只编译不链接得到了.o文件,在用ar工具归档成.a文件,这就是静态链接库文件;提供这些库和相应的头文件让他人声明和调用(定义你是不造的。) 静态(.a)链接库在用户链接最终得到可执行程序期间就把相应的库函数的代码段放进可执行程序里了,而且多个程序就算调用相同库函数也会重复嵌入,这样十分占用空间。 动态(.so)链接库在用户链接得到可执行程序期间并不加入相应库函数代码段,而是做标记,在执行期间,再把相应库函数代码段放进内存中相应位置执行,这样更优秀。 使用库函数注意:(gcc下默认用的动态链接库,-static使用静态链接库) 第一,包含相应的头文件;第二,调用库函数时注意函数原型;第三,有些库函数链接时需要额外用-lxxx来指定链接;第四,如果是动态库,要注意-L指定动态库的地址。 3).字符串处理函数: 注意:mem的参数,返回值多是void; memcpy //void *memcpy(void *dest, const void *src, size_t n); 确定src和dst不会overlap,则使用memcpy效率高 memmove // void *memmove(void *dest, const void *src, size_t n); 确定会overlap或者不确定但是有可能overlap,则使用memove比较保险 memset //void *memset(void *s, int c, size_t n); 用常量c来填充s所指向区域的前那个字节,用memset来初始化内存空间。 memcmp // int memcmp(const void *s1, const void *s2, size_t n); 比较s1和s2前n个中s1>s2,返回一个正数;s1=s2返回0;s1<s2返回一个负数。 memchr // void *memchr(const void *s, int c, size_t n); 在s指向的前n个内存区域找c是否存在 strcpy //char *strcpy(char *dest, const char *src); 拷贝一个字符串到另一个. strncpy //char *strncpy(char *dest, const char *src, size_t n); strcat //char *strcat(char *dest, const char *src); 字符串拼接函数 strncat //char *strncat(char *dest, const char *src, size_t n); strcmp //int strcmp(const char *s1, const char *s2); 看Ascll码,str1>str2,返回值 > 0;两串相等,返回0 strncmp //int strncmp(const char *s1, const char *s2, size_t n); strdup //char *strdup(const char *s); 将串拷贝到新建的位置处 ,需要free()函数搭配,头文件自然还需要malloc.h strndup // char *strndup(const char *s, size_t n); 在vs下无,在linux下有。 注意:下面的返回的是指针哟 strchr //char *strchr(const char *s, int c); 在一个串中查找给定字符的第一个匹配之处 strstr // char *strstr(const char *haystack, const char *needle); 在串中查找指定字符串的第一次出现 strtok //char *strtok(char *str, const char *delim); 字符串分割,第一次用后首个参数设为NULL,查找由在第二个串中指定的分界符分隔开的单词;后一个参数使用""弄起来的,不是''。注意源字符串会被改变,只保留其第一个字符。 ······· #include<stdio.h> #include<math.h> #include<string.h> int main(int argc,char **argv) { /* double a=16,b=0; b=sqrt(a); //需要-lm才能找到.so printf("sqrt(a) is %lf\n",b); */ char str[]="badmer"; char sor[]="student"; char *p="linux"; /* strcpy(str,sor); printf("the string is %s\n",str); strcpy(str,p); printf("the string is %s\n",str); strncat(str,p,4); printf("the string is %s\n",str); char* i=strchr(str,'u'); printf("the char location is %p\n",i); */ /* i=strtok(str,','); printf("the ,char location is %d\n",i); */ /* strcpy(p,str); //不可以的哦 printf("the string is %s\n",p); */ char *q="mad,cx"; /* memset(str,0,strlen(str)); printf("the string is %s\n",str); */ memmove(str,q,strlen(str)); printf("the string is %s\n",str); char *m=strtok(str,","); if(m) printf("the char is %s\n",m); m=strtok(NULL,","); if(m) printf("the char is %s\n",m); return 0; } 一般出现n修饰的是指定个数(字节或是字符);出现i修饰的是不区分大小写。 4).数学函数 1。真正的数学运算的函数定义在:/usr/include/i386-linux-gnu/bits/mathcalls.h,使用数学库函数的时候,只需要包含math.h即可。 2.使用sqrt时粗线错误:test_func.c:(.text+0x21): undefined reference to `sqrt' collect2: error: ld returned 1 exit status 这是链接错误,和编译错误(假如没头文件,编译错误:warning: incompatible implicit declaration of built-in function ‘sqrt’ [enabled by default])不同。 错误原因:他说没定义,那么就是没找到库函数咯,我们加上-lm,让他到libm库中去找相应函数 C链接器工作特点:链接器只是默认的寻找几个最常用的库,如果是一些不常用的库中的函数被调用,需要程序员在链接时明确给出要扩展查找的库的名字。链接时可以用-lxxx来指示链接器去到libxxx.so中去查找这个函数。 5).制作并使用链接库: 静态链接库: (1)第一步:自己制作静态链接库 gcc fun.c -o badmer.o -c ar -rc libbadmer.a badmer.o 首先使用gcc -c只编译不连接,生成.o文件;然后使用ar工具进行打包成.a归档文件 库名不能随便乱起,一般是lib+库名称,后缀名是.a表示是一个归档文件 注意:制作出来了静态库之后,发布时需要发布.a文件和.h文件。 (2)第二步:使用静态链接库 把.a和.h都放在我引用的文件夹下,然后在.c文件中包含库的.h,然后直接使用库函数。 第一次,编译方法:gcc test.c -o test 报错信息:test.c:(.text+0xa): undefined reference to `func' 第二次,编译方法:gcc test.c -o test -lbadmer 报错信息:/usr/bin/ld: cannot find -lbadmer collect2: error: ld returned 1 exit status 第三次,编译方法:gcc test.c -o test -lbadmer -L. 无报错,生成test,执行正确。 注意:库的名字是libbadmer.a gcc编译是命令里是-lbadmer (3)除了ar名另外,还有个nm命令也很有用,它可以用来查看一个.a文件中都有哪些符号 动态链接库: (1)第一步:自己制作静态链接库 gcc fun.c -o badmer.o -c -fPIC gcc -o libbadmer.so badmer.o -shared -fPIC是位置无关码,-shared是按照共享库的方式来链接。 注意:做库的人给用库的人发布库时,发布libxxx.so和xxx.h即可。 (2)第二步:使用 gcc test.c -o test -lbadmer -L. 编译成功,运行报错:error while loading shared libraries: libaston.so: cannot open shared object file: No such file or directory 没找到库,因为动态链接库是在运行时加载到内存的,固定目录没找到就错误了。 解决方法: 1).解决方法一: 将libbadmer.so放到固定目录下就可以了,这个固定目录一般是/usr/lib目录。 cp libbadmer.so /usr/lib即可 #解决方法二:使用环境变量LD_LIBRARY_PATH。操作系统在加载固定目录/usr/lib之前,会先去LD_LIBRARY_PATH这个环境变量所指定的目录下去寻找,如果找到就不用去/usr/lib下面找了,如果没找到再去/usr/lib下面找。所以解决方案就是将libaston.so所在的目录导出到环境变量LD_LIBRARY_PATH中即可。 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH/mnt/hgfs/winshare/my_work/c_test/4.6.preprocess/badmer_so/release_so$ 但是这种方法和当年装交叉编译工具链时一样,重启终端就不行了. 在ubuntu中还有个解决方案三,用ldconfig (3)ldd命令:作用是可以在一个使用了共享库的程序执行之前解析出这个程序使用了哪些共享库,并且查看这些共享库是否能被找到,能被解析(决定这个程序是否能正确执行)。