作为第一门语言是 C++ 的程序员,一直觉得对 C
语言的一些重要特性不清晰,对一些 C 程序惯用法也不了解。故借阅读 《C
程序设计语言》 一书的机会,将相关曾经遗漏的知识整理如下。
1. extern 声明
extern
关键字用于声明外部变量,注意声明与定义的不同:
- 定义(define):表示创建变量或分配存储单元
- 声明(declaration):说明变量的性质,但并不分配存储单元
当外部变量的定义出现在使用它的函数之前时,可以省略
extern
声明;反之,必须有 extern
声明(如:涉及多个源文件)。
Example:
1 2 3 4 5 6 7 8 9 10
| #include <stdio.h>
int n = 1;
int main(void) { extern int n; # extern declaration printf("%d\n", n); return 0; }
|
用 static
关键字修饰外部变量或函数,可以将其后声明的对象的作用域限定为被编译文件的剩余部分,其他文件不能访问该对象。
static
也可用于声明内部变量:该变量仅能在某函数内使用但一直占据存储空间。
2. 宏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #undef getchar
#define dprint(expr) printf(#expr " = %g\n", expr)
dprint(x/y);
printf("x/y" " = %g\n", x/y);
#define paste(front, end) front ## end
|
条件包含
example 1:
1 2 3 4 5 6
| #if !defined(HDR) #define HDR
#endif
|
等价于:
1 2 3 4 5 6
| #ifndef HDR #define HDR
#endif
|
example 2:
1 2 3 4 5 6 7 8 9 10
| #if SYSTEM == SYSV #define HDR "sysv.h" #elif SYSTEM == BSD: #define HDR "bsd.h" #elif SYSTEM == MSDOS: #define HDR "msdos.h" #else: #define HDR "default.h" #endif #include HDR
|
3. union
union
:在不同时刻保存不同类型和长度的对象的变量。
example:
1 2 3 4 5
| union u_tag { int ival; float fval; char *sval; } u;
|
union
实际上就是
struct
,它的所有成员相对与基地址的偏移量都为 0,此
struct
空间要大到足够容纳最宽的成员,并且,其对齐方式要适合于
union
中所有类型的成员。
4. 位字段 bit-field
example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
struct { unsigned int is_keyword : 1; unsigned int is_extern : 1; unsigned int is_static : 1; } flags;
flags.is_extern = flags.is_static = 1; flags.is_extern = flags.is_static = 0;
if (flags.is_extern == 0 && flags.is_static ==0) ...
|
字段不是数组,且没有地址,不能对其使用 &
运算符。
5. 文件访问
example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| FILE *fp = fopen(name, mode); fclose(fp);
int getc(FILE *fp);
int putc(int c, FILE *fp);
int fscanf(FILE *fp, char *format, ...); int fprintf(FILE *fp, char *format, ...);
int ferror(FILE *fp); int feof(FILE *fp);
char *fgets(char *line, int maxline, FILE *fp);
char *fputs(char *line, FILE *fp);
|