关键词
restrict官方库
limits
CHAR_BIT
CHAR_BIT 宏描述了当前系统一个byte包含几个bit
常用宏
offsetof
1  | #define offsetof(type,member)((size_t)&((type*)0)->member)  | 
解析:
0
(type)0    强行将0作为type类型的指针
((type)0)->member    获取member对象
&((type)0)->member         获取membe对象地址
(size_t)&((type)0)->member     将地址转化为size_t
文件I/O
文件
文本视图和二进制视图
通常对于文本文件使用文本视图,对二进制文件使用二进制视图,但是对于同一个文件,其存储的内容是一致的,关键在于怎么解析看待这个文件,一个文本文件也可以解析为二进制文件

在文本视图中,程序所看到的内容和文件的内容会有所不同
解释: C语言会对当前操作系统环境对文本信息做不同的解析,如写入一个换行符都写入了\n,如果操作系统是windows则是写入\n\r,linux则是\r
I/O级别
- 低级别I/O,由操作系统提供的I/O服务
 - 高级别I/O,由ANSI C提供的C语言标准I/O服务
 
优劣势:
- 标准I/O提供多个专用函数
 - 标准I/O自带缓冲区
 
标准文件
- 标准输入 stdin 读取默认的输入设备(p.s.键盘)
 - 标准输出 stdout 写入默认的标准输出(p.s.显示屏)
 - 标准错误 stderr 写入默认的标准输出(p.s.显示屏)
 
函数众
说道这里,有点无聊,来个程序先嗨一发,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int main(int argc, char* argv[]) {
    int ch;
    FILE* fp;
    long count;
    if(argc != 2) {
        printf("intput the file u want to open!");
        exit(0);
    }
    if((fp = fopen(argv[1],"r")) == NULL){
        printf("open file %s failed!", argv[1]);
        exit(0);
    }
    while((ch = getc(fp)) != EOF) {
        putc(ch, stdout);
        count++;
    }
    fclose(fp);
    printf("File %s has %d characters",argv[1], count);
    exit(0);
}
这个程序是干什么的,
- 从命令行接收参数,参数为要打开的文件
 - 打开相应的文件,将文件内容再输出到标准输出里,并统计文件内的字符数
运行结果:
./count count.c
fopen
一本正经的函数声明:1
FILE * fopen(const char * path, const char * mode);
 
传参说明
path:很easy,文件路径,默认在当前执行文件路径查找
| mode      |     意义|
| :——– | ——–:|
| r|   可读|
| w|   可写,可创建|
| a|   可追加,可创建|
| r+|   可读写|
| w+|   可读写,若问件存在,则初始化为0|
| a+|   可读追加写,可以新建|
| rb,wb,ab,ab+,a+b,wb+,w+b,ab+,a+b|   类似于上面,二进制模式|
额 好多,剩下的自己查
p.s. 注意带有w的都会把原先的内容清空掉,谨慎,谨慎
返回参数说明
FILE类型
- 文件指针
 - 不指向实际文件,而是指向一个文件的数据包(包含文件的各种信息,包括缓冲区,)
以上为C primer pluse的解释 那么FILE到底是如何定义的呢!
找到系统/usr/include/stdio.h下1
typedef struct _IO_FILE FILE;
 
将struct _IO_FILE 解析成了FILE再追,查到_IO_FILE在libio.h里1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42struct _IO_FILE {
  int _flags;		/* High-order word is _IO_MAGIC; rest is flags. */
  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;	/* Current read pointer */
  char* _IO_read_end;	/* End of get area. */
  char* _IO_read_base;	/* Start of putback+get area. */
  char* _IO_write_base;	/* Start of put area. */
  char* _IO_write_ptr;	/* Current put pointer. */
  char* _IO_write_end;	/* End of put area. */
  char* _IO_buf_base;	/* Start of reserve area. */
  char* _IO_buf_end;	/* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */
  struct _IO_marker *_markers;
  struct _IO_FILE *_chain;
  int _fileno;
  int _blksize;
  int _flags2;
  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
  /* 1+column number of pbase(); 0 is unknown. */
  unsigned short _cur_column;
  signed char _vtable_offset;
  char _shortbuf[1];
  /*  char* _save_gptr;  char* _save_egptr; */
  _IO_lock_t *_lock;
};
好吧,有点小复杂,不深究了。
getc putc
1  | int getc(FILE *stream)  | 
与getchar() putchar()类似 就是把输入输出可以重定位了,不只是标准输入输出
文件末尾的问题:getc()在读取一个文件末尾的时候,将会返回特殊值EOF,所以C语言只有在读到超过文件末尾的时候才能判断文件的末尾,所以为了避免读到空文件,对文件末尾的判断要加在循环开始的地方
puts
1  | int puts(const char *string);  | 
将字符串输出到标准输出上
fclose()
1  | int fclose( FILE *fp );  | 
返回值 0关闭成功 其余关闭失败
关闭一个文件流,简单易懂
但是也可能出现关闭失败的现象,比如移动硬盘被拔了,磁盘满了
fprintf fscanf
1  | int fprintf (FILE* stream, const char*format, [argument])  | 
rewind
1  | void rewind(FILE *stream);  | 
将文件流指针移到开始