C语言低级I/O主要是指read、write、open、creat这些函数,这些函数和其它语言的IO用法差不多,只有creat这个函数很少见,用法也不容易弄明白。下面还是以《C程序设计语言》里面的例子来说明。
#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#define PERMS 0666
void error(char *,...);
int main(int argc,char *argv[]){
int f1,f2,n;
char buf[BUFSIZ];
if(argc != 3){
error("Usage: cp from to");
}
/* O_RDONLY来自fcntl.h */
if((f1 = open(argv[1],O_RDONLY,0)) == -1){
error("cp: can't open %s",argv[1]);
}
if((f2 = creat(argv[2], PERMS)) == -1){
error("cp: can't create %s,mode %03o",argv[2],PERMS);
}
while((n = read(f1,buf,BUFSIZ)) > 0){
if(write(f2,buf,n) != n){
error("cp: write error on file %s",argv[2]);
}
}
return 0;
}
void error(char *fmt,...){
va_list args; /* 来自stdarg.h */
va_start(args,fmt);
fprintf(stderr,"error: ");
vfprintf(stderr,fmt,args);
fprintf(stderr,"\n");
va_end(args);
exit(1); /* 来自stdlib.h */
}
此程序在dev c++下运行通过,与书上的代码略有出入,有几点稍作说明:
1,这个程序的作用是从命令行输入两个参数,这两个参数分别代表,需要复制的文件名、复制到新创建的文件名。
2,BUFSIZ,来自stdio.h,代表每次读取到缓冲区数据的大小。
3,creat的格式申明如下:
int creat(char *name,int perms);
这个第一个参数比较好理解,代表文件名。
perms则比较复杂,代表创建文件权限。每个文件对应一个9比特位的权限信息(读,写和执行访问),前三位代表文件所有者的对该文件的操作权限,中间三位代表所有者组的权限,后三位代表其他成员的权限。而八进制1位正好代表二进制3位,所以0755这个数字中,0代表八进制,7代表二进制111,5代表101,列个表出来。
读 写 执行
7 1 1 1
5 1 0 1
5 1 0 1
1代表有权限,0代表没得该项权限。这种方式的权限设计是unix的特色,其实也可以应用于现在的企业应用系统之中。
4,va_list,va_start,va_end,vfprintf函数。前面三个函数都是为vfprintf服务的,而vfprintf函数与fprintf函数类似,只是参数形式不同,它按照字符串fmt要求的格式,把args的值挨个赋进去。要理清va_list,va_start,va_arg,va_end的关系,可以参看下面的代码:
void minprintf(char *fmt,...){
va_list ap;
char *p,*sval;
int ival;
double dval;
va_start(ap,fmt);
for(p = fmt;*p;p++){
if(*p != '%'){
putchar(*p);
continue;
}
switch(* ++p){
case 'd':
ival = va_arg(ap,int);
printf("%d",ival);
break;
case 'f':
dval = va_arg(ap,int);
printf("%d",dval);
break;
case 's':
for(sval = va_arg(ap,char *); *sval;sval++){
putchar(*sval);
}
break;
default:
putchar(*p);
break;
}
}
va_end(ap);
}
这个代码是简略版的printf。
va_list用于声明一个变量,该变量将依次引用各参数,本质上它一是指向字符的指针。
typedef char * va_list;
va_start将使va_list变量指向第一个无名参数。
va_arg,每次调用该函数,都将返回一个相应类型(根据第二个参数而定)的值,并将va_list指向下一个参数。
va_end,清理回收,其实就是将va_list定义的变量值为0(NULL)。