Unix C语言入门准备(二)

来源:互联网 发布:中国经济发展数据图表 编辑:程序博客网 时间:2024/04/30 18:47

一、使用程序直接调用库文件的函数

#include<dlfcn.h>

void *dlopen(const char *filename,int flag);

参数表(库文件路径,flag标记)。flag 比较常用的有两个:RTLD_LAZY  延迟加载,RTLD_NOW  立刻加载。

char *dlerror(void);

有错返回错误信息,没错返回NULL。

void *dlsym(void *handle,const char* symbol);

第一个参数为dlopen的返回值,第二个是函数名。

int dlclose(void *handle);

参数为dlopen的返回值。

最后在连接程序的时候要加选项 -ldl.(Link  with -ldl ."gcc code.c -ldl")

步骤:

#include<dlfcn.h>

1.用dlopen()打开一个库文件,返回void*;

2.用dlsym()按函数名打开一个函数,返回函数指针;

3.使用函数指针;

4.用dlclose()关闭库文件;

5.dlerror函数判断是否出错。“!=NULL”出错。

#include<stdio.h>#include<dlfcn.h>int main(void){void* handler=dlopen("./libmylib.so",RTLD_NOW);//打开库文件返回void*char* error=dlerror();//判错if(error){printf("open error\n");return -1;}double (*f)(double,double);//定义函数指针f=dlsym(handler,"add2");//返回函数名error=dlerror();if(error){printf("sym error\n");return -1;}double r=f(2.0,3.0);printf("r=%lf\n",r);dlclose(handler);return 0;}

二、C程序员错误信息的处理

1.什么是错误处理?程序中有正确的分支和错误的分支,关于错误的情况如何处理,就是错误处理。错误处理的代码不影响错误是否发生。

2.C程序员处理错误的方式:(常规方式) 

(1)返回-1代表错误。      

    a.如果-1不是函数的有效返回值,直接返回-1代表错误。   

    b.如果-1是函数的有效返回值,用-1代表错误,用指针取返回值。 

(2)返回NULL代表错误。      

     一般来说,返回值是指针类型时,用NULL代表错误。 

(3)不需要考虑错误处理的函数 返回void

练习:写4个函数(独立函数)   

     第一个函数实现求两个整数的最大值,如果相等返回错误。(b)  

     第二个函数返回一个0-10的随机数,如果随机数是0,返回错误。(a)  

     第三个函数传入一个字符串,如果是"error",返回错误,其他情况,返回"ok"(2)  

     第四个函数 打印传入的一个字符串(3)

#include<stdio.h>#include<time.h>#include<stdlib.h>#include<string.h>int max(int a,int b,int *pi){if(a>b)*pi=a;else if(a==b)return -1;else *pi=b;return 0;}int rand10(void){srand(time(0));int r=rand()%11;if(0==r)return -1;return r;}char* iserror(const char* s){if(0==strcmp(s,"error"))return NULL;return "OK";}void print(char* str){printf("%s\n",str);}int main(void){int x;int res=max(2,3,&x);if(res==-1){printf("error\n");return -1;}printf("max=%d\n",x);res=rand10();if(res==-1){printf("error\n");return -1;}printf("res=%d\n",res);char *ps=iserror("eror");if(ps==NULL){printf("strerror\n");return -1;}printf("%s\n",ps);print("hello");return 0;}


 

三、C语言中没有string,字符串用两种方式表示:
char* s1;
char  s2[20];
其中,s1可以用"="赋值;s2只能用"="初始化,不能用"="赋值,s2的赋值使用strcpy函数。如果s1="aaa"(字面值),不支持strcpy()。
常用的字符串函数:
strcpy()  ---  赋值
strlen()  ---  取长度
strcat()  ---  追加内容
strcmp()  ---  比较两个字符串(通常判定字符串相同)
strncmp() ---  比较两个字符串的前n 个字符

 

四、C语言对错误的处理也有支持,主要是:
定义了一个全局变量errno,存储错误的编号。
定义了strerro/perror/printf("%m")三个函数转换错误编号和错误信息,后两个可以自动打印。
注:不是所有的函数都使用errno处理错误。

#include<string.h>
char *strerror(int errnum);
#include<stdio.h>
void perror(const char *s);[参数为自定义信息部分]
#include<errno.h>
const char *sys_errlist[];
int sys_nerr;
int errno;

 

五、环境变量和环境表在程序中的使用。
C语言中,提供了环境表变量environ存储环境变量的各种信息,类型是一个char**(字
符指针数组),需要extern。environ存储的是首地址。

【环境表:每个程序都会接收到一张环境表,是一个字符指针数组。数组以NULL作为
结束。全局变量environ保存了该数组的首地址。】
常用函数
#include <stdlib.h>
getenv     返回指向name关联的value的指针,没有返回NULL
格式:char *getenv(const char *name);
putenv     将形式为"name=value"的环境变量放入环境表
格式:int putenv(char *string);
setenv     将name设置为value,第三个参数表示是否覆盖。0不覆盖。非0,覆盖
格式:int setenv(const char *name, const char *value, int overwrite);
unsetenv   将name移除。
格式:int unsetenv(const char *name);
clearenv   清除环境表中所有项。
格式:int clearenv(void);
The  clearenv() function clears the environment of all name-value pairs
and sets the value of the external variable environ to NULL.

 

#include<stdio.h>#include<stdlib.h>int main(int argc,char **argv,char **env){extern char **environ;printf("%p,%p\n",environ,env);char *value=getenv("LANG");printf("value=%s\n",value);putenv("VAR=ABC");printf("var=%s\n",getenv("VAR"));//ABCputenv("VAR=123");printf("var=%s\n",getenv("VAR"));//123setenv("VAR","456",0);//0,不覆盖printf("var=%s\n",getenv("VAR"));//123setenv("VAR","789",1);//1,覆盖printf("var=%s\n",getenv("VAR"));//789return 0;}


 

六、Unix/Linux的内存管理  

 1.    STL         -    内存自动分配和回收    

       |   

       C++          -    new 分配,delete 回收    

       |   

       C           -    malloc分配,free 回收   

       |  

      Linux系统函数   -    brk/sbrk    

       |  

     Linux系统函数  -    mmap分配 / munmap回收        (用户层)         ---------------------------------------------------------------   

     kmalloc  vmalloc 等                       (内核层/系统层)

   2.Unix/Linux内存管理机制:  

虚拟内存地址 - 在Unix/Linux中,每个进程都有0-4G的虚拟内存地址(其实就是数字)。虚拟内存地址必须映射到物理内存/硬盘文件空间上才能存储数据。如果虚拟内存地址没有映射物理内存/文件,会产生段错误/总线错误。内存分配就是把一部分虚拟内存地址和物理内存映射起来。程序员看到的都是虚拟内存地址。

   其中0-3G是用户使用的,叫用户空间,3G-4G是操作系统使用的,叫内核空间。用户空间不能直接进内核空间,但可以通过系统函数(系统调用)进入内核空间。内存的分配和回收不是以一个字节作为单位,以一个内存页(4096字节 4KB)作为单位。

   3.Unix/Linux的进程和程序:

     程序   就是 可执行的文件(硬盘上的) 

     进程   就是 正在运行的程序(内存中的)

     内存针对的是进程,进程的内存空间的组成: 

      1.代码区 - 存函数的代码,函数所在区,只读区。 

      2.全局区 - 存全局变量和static变量,读写区 

      3.bss段  - 未初始化的全局变量,在main执行前bss段,自动清零。 

      4.栈区   - 局部变量,函数参数,返回值等,内存自动管理  

      5.堆区   - 自由区,malloc new分配的内存,堆区的内存用free/delete回收,否则内存泄漏。 

      注:代码区附近有一个常量和字符串常量区,存常量和字符串字面值("string"),也是只读区,但是并入代码区。

 

 

原创粉丝点击