C语言
C 语言是一种通用的、面向过程式的计算机程序设计语言。1972 年,为了移植与开发 UNIX 操作系统,丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言。
C 语言是一种广泛使用的计算机语言,它与 Java 编程语言一样普及,二者在现代软件程序员之间都得到广泛使用。
当前最新的C语言标准为 C11 ,在它之前的C语言标准为 C99
类型运算符与表达式
变量名
变量名的开头必须是字母或下划线,不能是数字
变量名中的字母是区分大小写的
变量名绝对不可以是C语言关键字
变量名中不能有空格
数据类型及长度
| 类型 | 存储大小 | 值范围 | 
|---|---|---|
| char | 1字节 | -128到127或0到255 | 
| unsigned char | 1字节 | 0到255 | 
| signed char | 1字节 | -128到127 | 
| int | 2或4字节 | -32,768到32,767或-2,147,483,648到2,147,483,647 | 
| unsigned int | 2或4字节 | 0到65,535或0到4,294,967,295 | 
| short | 2字节 | -32,768到32,767 | 
| unsigned short | 2字节 | 0到65,535 | 
| long | 4字节 | -2,147 ,483,648到2,147,483,647 | 
| unsigned long | 4字节 | 0到4,294,967,295 | 
常量
字符常量 常量表达式 枚举常量
声明
算术运算符
| 名称 | 运算符号 | 举例 | 
|---|---|---|
| 加法运算符 | + | 2+10=12 | 
| 减法运算符 | - | 10-3=7 | 
| 乘法运算符 | * | 2*10=20 | 
| 除法运算符 | / | 30/10=3 | 
| 求余运算符(模运算符) | % | 23%7=2 | 
| 自增运算符 | ++ | int a =1;a++ | 
| 自减运算符 | -- | int a =1;a-- | 
关系运算符与逻辑运算符
| 符号 | 意义 | 举例 | 结果 | 
|---|---|---|---|
| > | 大于 | 10>5 | 1 | 
| >= | 大于等于 | 10>=10 | 1 | 
| < | 小于 | 10<5 | 0 | 
| <= | 小于等于 | 10<=10 | 1 | 
| == | 等于 | 10==5 | 0 | 
| != | 不等于 | 10!=5 | 1 | 
| 符号 | 意义 | 举例 | 结果 | 
|---|---|---|---|
| && | 逻辑与 | 0&&1 | 0 | 
| ` | ` | 逻辑或 | |
| ! | 逻辑非 | !0 | 1 | 
类型转换
- 自动转换
- 强制转换
函数与程序结构
函数的基本知识
- 函数的定义形式 - 返回值类型 函数名(参数声明表){ 声明和语句 }
外部变量
作用域规则
头文件
静态变量
static int a;
寄存器变量
register int x;
register变量将放在机器的寄存器中
程序块结构
初始化
外部变量和静态变量都将被初始化为0
递归
C预处理器
- 文件包含 - #include "文件名" #include <文件名>
- 宏替换 - #define a b- 不会替换字符串中的内容 - 带参数的宏
- #undef
- 双井号嵌套
 
- 条件包含 - #ifndef HDR #define HDR #endif
指针
指针与地址
p = &c; // p为指向c的指针
y = *p; // 现在y的值的c的值
指针与函数参数
void swap(int *x,int *y){
    int tmp = *x;
    *x = *y;
    *y = tmp;
}
指针与数组
数组本质也是一个指针
但是指针是一个变量,数组名不是一个变量
地址算术运算
- 相同类型指针之间的赋值运算
- 同整数间的加减法运算
- 指向相同数组的两个指针减法或比较运算
- 将指针赋值为0
字符串与指针
void reverse(char *s,int n){
    if (n<0){
        return;
    }
    putchar(*(s+n));
    reverse(s,--n);
}
指针数组以及指向指针的指针
char *sa[20];
int main(){
    int x;
    int *xp = &x;
    int **xpp = &xp;
    **xpp=15;
    printf("%d",x);
}
多维数组
int a[i][j];
指针数组的初始化
指针与多维数组
char *s[]={"123","321","1111"};
命令行参数
int main(int argc,char *s[]){return 0;}
指向函数的指针
int fun(int a) {
  return a+6;
}
void fun1(int (*f)(int)) {
  printf("%d \n", (*f)(48))
}
int main(int args, char *args[]) {
  fun1(&fun);
  return 0;
}
复杂声明
结构
基本知识
struct{
    int x;
    int y;
} point;
struct poinit p;
p.x=1;
结构与函数
- 结构指针 - struct point *pp; (*pp).x=5; y = pp->x;
结构数组
struct poinit ps[20];
结构指针
结构体中的数据对齐问题
自引用结构
struct{
    int x;
    int y;
    struct point *p;
} poinit;
表查找
类型定义
typedef char* String
String s = "123";
联合
union ut{
    char a;
    int b;
    long c;
}u;
u.c=1L;
位字段
输入与输出
标准输入输出
- getchar
- putchar
格式化输出-printf
| 字符 | 参数类型;输出形式 | 
|---|---|
| d,i | int类型;十进制数 | 
| o | int类型;无符号八进制数(没有前导0 ) | 
| x, X | int类型;无符号十六进制数(没有前导0x或0X ), 10~15分别用abcdef或ABCDEF表示 | 
| u | int类型;无符号十进制数 | 
| c | int类型;单个字符 | 
| s | char *类型;顺序打印字符串中的字符,直到遇到'\0'或已打印了由精度指定的字符数为止 | 
| f | double类型;十进制小数[- ] mdddddd,其中d的个数由精度指定(默认值为6 ) | 
| e, E | double类型; [-]mdddd e +xx或[ - ]mddddd E土比,其中d的个数由精度指定(默认值为6 ) | 
| g,G | double类型;如果指数小于-4或大于等于精度,则用各e或8E格式输出,否则用8f格式输出。尾部的0和小数点不打印 | 
| P | void *类型;指针(取决于具体实现) | 
| % | 不转换参数;打印一个百分号% | 
变长参数表
void pr(int a,...){
  va_ list ap;
  int i;
  va_ start(ap,a);
  
  for(i=0;i<5;i++){
    printf( "%d" ,va_ arg(ap,int));
  }
  va_ end(ap);
}
int main(int argc,char *args[]){
  pr(1,2,3,4,5,6);
}
格式化输入-scanf
转换字符指定对输人字段的解释。对应的参数必须是指针,这也是C语言通过值调用语义所要求的
| 字符 | 输人数据;参数类型 | 
|---|---|
| d | 十进制整数; int*类型 | 
| i | 整数; int*类型,可以是八进制(以0开头)或十六进制(以0x或0x开头) | 
| o | 八进制整数(可以以0开头,也可以不以0开头) ; int *类型 | 
| u | 无符号十进制整数; unsigned int* 类型 | 
| x | 十六进制整数(可以0x或0X开头,也可以不以0x或0X开头) ; int *类型 | 
| C | 字符; char *类型, 将接下来的多个输人字符(默认为1个字符)存放到指定位置。该转换规范通常不跳过空白符。如果需要读人下一个非空白符,可以使用%1s | 
文件访问
int main(int argc,char *args[]){
  FILE *fp;
  FILE *fp1;
  char c;
  fp = fopen(" . /reverse1.c" ,"aw");
  fp1 = fopen("./reverse.c","r") ;
  while((c=fgetc(fp1)) != EOF){
    fputc(c,fp);
  }
  fputs("test",fp);
  fclose(fp);
  fclose(fp1);
}
错误处理
- stdout
- stderr
行输入和行输出
- fgets
- fputs
其他函数
UNIX系统接口
文件描述符
内核(kernel)利用文件描述符(file descriptor)来访问文件。 文件描述符是非负整数。 打开现存文件或新建文件时,内核会返回一个文件描述符。 读写文件也需要使用文件描述符来指定待读写的文件。