+
-
^
$
*
?
[]
.
\d
{}
正则
第1课 点号(不算元字符) 可以匹配任何单字符 (换行符除外),即123...abc...
若匹配汉字,则要两个点号
52067
"5...7" 或 "\d{2,12}"
第2课 星号 * 表示之前元素出现任意次或0次
4.*8 438 412345678
第4课 问号? 表示前面的元素出现0次 或 1次
加号+ 表示前面的元素必须出现1次或以上
4.?8 48 或4X8 问号表示前面的出现或不出现都可以(0次或1次)
4.+8 除了48之外,其他的4*8都可以,至少1次或以上
4.*8 表示前面元素出现0次或任意次
ascii码:
0 ~ 9 对应的ascii是: 48 ~ 57
A ~ Z 对应的ascii是: 65 ~ 90
a ~ z 对应的ascii是: 97 ~ 122
8进制转二进制: 3位一取
16进制转二进制: 4位一取
2进制: 0b10
8进制: O10
16进制:0x10
正数三码合一:原码=反码=补码
负数的反码 = 原码的符号位不动,其他位取反
负数的补码 = 反码 + 1
内存中的数 全是补码的形式
对补码 再求补码 = 原码
对补码 再求反码 + 1 = 原码
char 其实是整形,并不是字符变量
而Java中的char是字符变量
低位(char) -->高位(short),位扩展时 正数补0,负数补1
scanf不要随便加空格及回车\n
输入一个十进制,转换成16进制数
输入一个字符,显示其ascii码
int + char 结果4字节,说明仍为int
1.短字节向长字节看齐
2.有符号..向 无符号..看齐
3.整型.. 向浮点..看齐
4.单精度.. 向双精度..看齐
口诀: 先扩展,再看齐,后运算
10进制 10
8进制 O10
2进制 0b10
16进制 0x10
O22表示十进制的18
0b101表示十进制的5
0x21表示十进制的33
自增自减必须针对 常量
表达式为真:即为非零
表达式为假:即为0
C运算级:
! ++ --
* / %
+ -
> < >= <= ==
&&
||
=,+=,-=,*=
,
int a[20] a[0]~a[19]
8个开关一组,为一个字节
int 4个字节,4X8 =32位
数组不能整体赋值
指针是一个变量,64位8字节; 32位4字节
地址是常量,指针是变量
char 1个字节,常量不是空间,没有地址
单独的数组名arr,相当于其第一个元素arr[0]地址,即&arr[0]
数组名是首元素地址
打印指针%p
指针有一个特点: 指针变量 + 1,其结果相当于加了一个其指向的变量所占的地址的字节数
int *p = (int *)5
p++ p== 5 + 4 =9
char *q = (char *)5
q++ q== 5+1=6
注:int 占4个字节,char 占1个字节
*(p+3) 等价于 p[3]
arr[3] = 9 等价于*(&arr[0] + 3) = 9
即*(p + 3) = 9即 p[3] = 9
arr[5] = {1,2,3,4,5}
arr[3] = 4 其实 *(arr + 3) = 4
3[arr] = 4 其实*(3 + arr) = 4 二者等价
指针是地址的变量
数组是地址的常量
所以数组不能直接赋值
不能返回一个局部变量的地址(因为随时可能被释放)
int *p[10] : 80
* 和 [] 平级
平级右结合: 数组int *P;数组里的每一个元素为指针(指向整型常量的指针)
函数名是函数的入口地址
第1题:int *p[10] p是什么类型?
把p遮住,剩下的就是p的类型int *[10]
[]方括号是 加 i 后取*
例如:arr[0] = *(arr + 0)
平级右结合,说明这是一个数组,它有10个元素
int * Arr,得到数组元素的类型
所以每个元素为指向整型的指针
所以,综上所述:int *p[10]中的p是一个数组(因为p离[]最近)
数组里的元素是一个指向整型的指针
int *p[10] 当我们盖住p[10]后的东西 就是p[10]的类型
int *A 即p[10]是一个指向整型的指针
所以: int b = 2; p[10] = &b; *p[10] = 67;则b = 67;
第2题:int (*p)[10]的长度为4,为什么?
首先,要看p是什么类型,我们就把p遮住后,看剩下的东西是什么
int (*)[10]
所以p的类型就是一个指针 ,那p指向的东西是什么呢?
先看一下这个: int *pp,这儿的pp指针指向的是整型
p指向的是*p,所以我们遮住*p
int Arr[10], 有10个整型元素的数组,长度为4X10字节
总结: int (*p)[10] 这一个指针,因为p指向的是*p
要得到p的指向,我们就把*p看成一个整体
即:int Arr[10]
所以,它指向一个有10个元素的数组,即p是指向数组的指针
第3题:int **p 是什么东东?
p离*最近,说明p是一个指针
指向的是什么呢?我们就把*p看成一个整体
即:int *A
我们发现A也是一个指针,A是指向整型的指针,所以p是一个指向指针的指针
即二级指针,二级指针可以用来改变指针的指向
第4题:int (*func(void))[10]这是一个什么东东?
func与()相连,说明这是一个函数,函数的参数是void
函数的返回值是什么呢?
我们把func(void)看成一个整体
int (*A)[10],这是个什么呢?
这是一个指针,指向的是什么呢?
我们把*A看成一个整体
int Arr[10] ,所以知道了指向的是一个具有10个整型元素的数组
综上所述:int (*func(void))[10]是一个返回值为:
指向一个具有10个整型元素的数组的指针 的函数
第5题:int *func(int) 这是一个什么东东?
func和()相连,说明这是一个函数
函数的参数是整型,那返回值是什么东东?
为此,我们把它看成一个整体
函数的返回值是int *A, 这是一个指针,指向的是一个int
综上所述:int *func(int)这是一个参数为int,返回一个指向int的指针的函数
第6题:int (*p)(int)是一个什么东东呢?
首先p和*在一起,说明这是一个指针,那么指向什么东东呢?
我们把*p看成一个整体int Func(int),
这是一个函数,参数和返回值都是int
所以:综上所述,p是一个函数指针,即指向一个函数的指针
第7题:int (*(*p[10])(int)(int)这是一个什么东东呢?
p和[]在一起,所以是一个数组,数组有10个元素,看成一个整体就是
int (*(*Arr)(int)(int)
数组的旁边是*,说明数组里的元素是一个指针,那指向什么呢?
我们把*Arr看成一个整体
int (*E)(int)(int),看到还是一个指针,那这个指针又指向什么呢?
我们把*E看成一个整体
int func(int)(int)
func和()连在一起,说明这是一个函数
函数的参数是int,那函数的返回值是什么呢?
我们把func(int)看成一个整体
int B(int),这是一个函数,参数和返回值都是整型
综上所述:大家自己看吧,我先吐一会儿
第8题:int (*(*p[10])(int))(int)这是什么东东呢?
首先p和[]在一起,是一个数组,数组有10个元素
把它们看成一个整体int (*(*arr)(int))(int)
arr和*在一起,说明数组里的元素是一个指针
那么指向的是什么呢?我们把*arr看成一个整体
int (*Func(int))(int),Func和()在一起,说明是一个函数
函数的参数是int,那函数的返回值是什么呢?
我们把Func(int)看成一个整体
int (*B)(int), B和*在一起,说明是一个指针
指向的是什么呢?我们把*B看成一个整体
int Function(int)这是一个函数,返回值和参数都是int
因此,综上所述:我要先吐会儿
看不见的字符:尾零'\0'
尾零是一个字符
"h" 由 'h' + '\0' 2个字节
'h' 是一个数字,占4个字节 (int)类型
char *p = "beyond"
当我们写"beyond"时,即告诉编译器,在只读数据段存6+1个字符(尾零也是一个字符,每一个字符在字符串中占一个字节)
记住"beyond"表达式的值,表示字符串第1个字符的地址
注意:只读数据段的内容不容修改
char arr[64] = "beyond",会把只读数据段内容,复制到栈(sgt)里面,所以可以更改
"beyond"占6+1个字节;但有效字节长为6
专门求有效字符长度的函数strlen(str),会算到第1个'\0'为止
整数型 atio(文本型) 函数的作用是:
将字符转换成数字,遇到非数字或第2个负号则停止转换
atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数,int atoi(const char *nptr) 函数
strcmp(文本1,文本2)函数,如果两个文本相等则返回零,如果文本1 > 文本2,则返回正数
文本型 strcpy(目标,源文本)
当一个指针的指向不确定的时候,我们称之为野指针
strcpy中目标不能为野指针
strcat(头,尾)拼接,头必须空间足够
strstr(文本,查找文本) 当找不到时为Null
strtok(文本,分割符) 分割文本
文本为可变字符串
位运算:针对补码的运算
&按位与 ~按位取反
|按位或 <<左移
^按位异或 >>右移
相与,用的是补码(正数3码合一)
负数的补码是反码+1
原码
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:
[-1]原 = 1000 0001
反码
反码的表示方法是:
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
[-1] = [10000001]原 = [11111110]反
补码
补码的表示方法是:
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
[-1] = [10000001]原 = [11111110]反 = [11111111]补
例如: 5 & 3 = 1
5是0101
3是0011
例如:5 & -1 = 5
5是0101
-1的补码是全1
char a = 5; char b = 3 一个字节8位
0000 0101 是 5
0000 0011 是3
如果b = -1
-1的补码是1111 1111
那么5 | 3 = 7
5 | -1 = -1
任何数与 -1 进行 或运算,结果都为-1
异或 a ^ b ,相同为假0,不同为真1
5 ^ 3 = 6
5 ^ -1 = -6
如果两个数,按位异或后,第一位符号位是1,说明是负数,则还要对其取补码,算出补码的值就是异或运算结果的值
按位取反: ~ 5
如果正数取反后,第一位符号位是1,说明是负数,则要对其取补码,补码的值就是取反运算结果的值
例如: ~ 5
0000 0101 按位取反后 1111 1010,首位是1,是负数,所以要再一步求得补码后,才知道运算的结果
对1111 1010 求补码: 符号位不变,其他位取反 + 1 = 1000 0101 + 1 = 1000 0110 = -6
负数进行取反运算时时, 要先把负数从原码变成补码,然后再对负数的补码取反