C Language
汇编语言
汇编语言是直接面向处理器的、面向机器的程序设计语言,属于低级语言
不同的处理器有不同的汇编语言语法和编译器,编译的程序无法在不同的处理器上执行,缺乏可移植性
C语言特点
允许直接访问物理地址,能进行位操作,实现汇编语言的大部分功能,可直接对硬件进行操作,兼有高级和低级语言的特点
目标代码质量高,程序执行率高,只比汇编程序生成的目标代码效率低10%-20%
程序可移植性好,基本上不做修改就能用于各种型号的计算机和各种OS
C语言结构
hello.c –> 预处理器cpp –> hello.i –> 编译器ccl –> hello.s(汇编程序 文本) –> 汇编器AS –> hello.o(可重定位目前程序 文本) –> 链接器LD –> 可执行位目标程序 文本
预处理器执行以#开头的命令,类似于编辑器,可以给程序添加和修改内容
常量命名
宏定义
#define 后面无分号
标识符
- 区分大小写
- 标识符可以含有字母、数字和下划线,但是必须以字母或者下划线开头
格式化的输入输出
两个%输出一个% –
printf("%f%%", 1.)
输出 1.00000%%m.nf
m位,n位小数在寻找数的初始位置时,
scanf
函数会忽略空白字符(包括水平符、制表符、换页符和换行符)123456void main(){int num1, num2;scanf("%d%d", &a, &b);printf("%d\t%d\n", num1, num2);}12345678910input:12 78output:12 78input:1278output:12 78
表达式
当操作数为整数和浮点数混合,结果为浮点数
赋值运算符,向左看齐
12int i;i = 72.99f; /*i is now 72*/
运算符
优先次序:算术运算符 > 关系运算符 > 赋值运算符
(由高到低 依次减小)
自增自减 》+ -
一元逻辑 !
乘法类 */%
加法类 + -
关系运算符 > < >= <=
判等运算符 == !=
二元逻辑 && ||
赋值 = *= /= %= += -=
C89没有定义布尔值类型
为了程序便于理解,可以定义宏
12C99提供了_Bool类型
_Bool flag;
C99提供了一个新的头文件
<stdbool.h>
, 可以写bool flag;
控制表达式:switch后边的表达式要求是整型,不能用浮点数和字符串
case 常量表达式
每个分支标号后可以跟任意数量的语句 语句最后通常是break语句
循环
- break & continue
- break 语句从循环体跳出,提前结束循环,可以用在switch和循环中
- continue 跳出本次循环,跳过循环体下面尚未执行的语句,进行下一次是否执行循环的判断,只能用在循环中
基本类型
int 32位,short int 16位, long int, long long int
浮点类型:float单精度浮点数 32位,double双精度浮点数 64位,long double扩展精度浮点数
字符型:’a’为97, ‘A’为65, ‘0’为48, ‘ ‘为32
char 8位
字符处理函数:
123ch = toupper(ch);ch = tolower(ch);读写字符:
scanf 函数不会跳过空白字符,为了强制scanf 函数在读入字符前跳过空白字符,需要加上一个空格
1scanf(" %c",ch);对于单个字符的输入和输出,可以使用
getchar()
和putchar()
函数来代替12putchar(ch);ch = getchar();sizeof 运算符
确定存储空间类型所需要的空间大小
sizeof(char) = 1
数组
- 指定初始化 C99:
|
|
运算符sizeof可以确定数组的大小(字节数)
Eg: int a[10], sizeof(a) = 40
可以用sizeof来计算数组元素的大小,比如a[0]
可以得到数组的长度,sizeof(a)/sizeof(a[0])
函数
函数的定义,形式参数
函数的调用,实际参数,将值复制给形式参数
在函数执行过程中,对形式参数的改变不会影响实际参数的值,因为形式参数中包含的是实际参数值的副本
可以在调用前先进行,函数声明
指针
指针 – 变量的地址,存放数据的内存地址
指针变量是存放变量地址的变量,用来指向另一个变量,是一种变量,该变量存放的数据就是内存地址
pointer -> 010100011 address of variable i, p指向i, 指向就是将变量的地址存放到指针变量中
*
表示指向关系,称为指针运算符,运算对象为地址
指针变量的定义和初始化
|
|
指针赋值,指针p与q指向相同的位置
函数的参数,指针类型作为参数的作用是将一个变量的地址传递给函数进行处理,数组名作为函数参数,传递的是地址而不是数值。
Eg:
|
|
指针和数组
指针和加法
p指向a[i],则p+j指向元素a[i+j]
两个指针相减时,结果为指针之间的距离,以数组元素的个数为度量
p++ = (p++)
用数组名作为指向数组的第一个元素的指针
12*a = 7;*(a+1) = 12;a+1 和 &a[i] 等同,均表示指向数组a中元素i的指针
*(a+1) 和 a[i] 等同,均表示数组a中的元素i自身
快速处理多维数组,将二维数组初始化0
12for(p = &a[0][0]; p <= &a[ROWS-1][COLS-1]; p++)*p = 0;
字符串
字面量的存储:当编译器遇到一个长度为n的字符串字面量时,给该字符串分配n+1个字节的内存空间,外加一个额外的空字符,用于标志字符串的结束,空字符是一个所有比特为0的字节,用转义序列
\0
表示例如”abc” – “abc\0”
12char *p;p = "abc";字符串字面量 & 字符常量
“a”是以指针表示的,’a’是以整数表示的
char date[] = “June 14” – date为数组,存储的字符可以修改
char *date = “June 14” – date为指针,date所指向的字符串字面量不能修改的
char *p; 没有为字符串分配空间
字符串输出:
printf()
,puts()
–会写一个额外的新行符字符串读取:
scanf("%s", str);
str是指针,不必在str前面放置&运算符,当遇到scanf()
时,该函数跳过空白,然后读入字符并存入str指向的空间,直至遇到一个空白字符scanf()
会存放一个空字符在字符串的后面- 新行符、空白和tab符,均导致
scanf()
停止读取 - 要读取整行输入,可以使用
gets()
函数,特点:- 读取输入不会跳过开始的空白
- 直到找到新行符才停止读入
- 不存储新行符,而用空字符代替
使用C字符串库
#include<string.h>
strcpy(char *s1, char *s2);
copysize_t strlen(const char *s);
strcat(char *s1, char *s2);
concatenationint strcmp(const char *s1, char *s2);
if (strcmp(str1, str2)<0) means str1<str2; (strcmp(str1, str2)<=0) means str1<=str2复制字符串
|
|
字符串数组:
参差不齐的数据(ragged array),可以有不同长度的行,以便节省空间
char *planets[] = {“Mercury”, “Venus”, “Earth”, “Mars”, “Jupiter”, “Saturn”, “Uranus”, “Neptune”, “Pluto”}
命令行参数
argc argument count
argv argument vector
argv[0] 指向程序名,argv[1]~argv[argc-1] 指向余下的命令行参数
编写程序
#include
#include \
#include “filename” 查找当前路径,然后查找系统头文件所在的路径