第一章
1,数据类型——不同类型数据所占字节数(32位)
1,int——4
2,short——2
3,float——4
4,long int——4
5,double——8
2,常见数据类型
3.14——这是double类型
3.14f——这是float类型
字符类型
1、'a' 单引号 表示取a的ASCII值
2、字符在计算机及存储的是ASCII
3、'a' ==97,二者完全等价
4,sizeof('a')是四字节
转义字符
'\n' 换行 '\t' tab ’//‘ /
printf("A:%d\n", '0');//48
printf("B:%d\n", '\0');//0
printf("C:%d\n", 0);//0
printf("D:%d\n", "0");//字符‘0’地址
''取的是字符的ASCII值 ""取的是字符串的首元素的地址
3,格式控制
3 printf("##############\n");
4 //%5d 表示占5个终端位宽 右对齐
5 printf("##%5d##\n",123);
6
7 //%‐5d 表示占5个终端位宽 左对齐
8 printf("##%‐5d##\n",123);
9
10 //%05d 表示占5个终端位宽 右对齐 不足补0
11 printf("##%05d##\n",123);
12
13 //千万不能写 %‐05d
14 //printf("##%‐05d##\n",123);
15
16 //%5.2f 5表示总位宽为5 .2表示小数位保留2位
17 printf("##%5.2f##\n", 3.14159f);
typedef
为已有的类型重新 取个别名。
1、用已有的类型 定义 一个变量
2、用别名 替换 变量名
3、在整个表达式的前方加上 typedef.
1 案例1:
2 int INT32
3 typedef int INT32;
4
5 案例2:给int arr[5] 取个别名 ARR
6 typedef int ARR[5];
7 ARR arr;//arr就是一个拥有5个int元素的数组
4,数据类型转换
自动转换,往高出转,举例
//由于char short自身字节数 过小 很容易溢出
//所以 只要char short参加运算 都会将自身转换成int
强制 类型转换 只是临时的转换 当前语句有效 在后面的语句中不会更改x的值
5,运算符
1算数运算符
a /b 如果a b为整数 表示取整 如果 a b只要有一个为浮 点数 则表示除法运算结果还是浮点数
取整 %取余 必须为整数
2,逻辑运算符
逻辑非!//C语言 0为假 其他都为真 ‐1
逻辑与 A && B 如果A为假 系统不会执行B 这就是&&的短路特性
&:按位与 语法:全1为1 其他为0
|:按位或 语法:有1就为1 全0才为0
~:按位取反 语法:0变1 1变0
^:按位异或 语法:相同为0 不同为1
<< 左移运算符: 左边丢弃 右边补0,左移n位变成2的n次方
3,其他运算符
逗号运算符 data1 = 3,4,5,6 //结果是3,先赋值 data2 = (3,4,5,6);结果是6
表达式1 ? 值1:值2 语法:如果表达式1 为真 整个表达式的值为“值1” 否则 为“值2”
a *= b; ==> a= a * b; 注意:=号 右边必须看成一个整体,a+b看成(a+b)
4,优先级,算数,关系,逻辑,赋值
6,循环
continue;//结束本次循环 立即从当前位置直接 进入下一次循环
break;//只能跳出离它最近的一层循环,或者在swich语句中
第二章数组
1、数组的定义
需求:请定义一个数组 该数组 有10个元素 每个元素为int 在定义的时候: a、arr[] arr和[]结合是数组
b、将确定的元素的个数放入 []中
c、用元素的类型 定义一个普通变量
d、从上往下整体替换。 int arr[10];
注意: 1、数组名 arr 不能和其他变量名 同名 2、数组的元素小标是从0开始:0~9 3、数组的元素 分别是:arr[0]、arr[1]~arr[9], 如果访问arr[10]数组越界。 4、数组的元素 等价于 普通变量 5、在定义数组的时候 ,[]里面的值 不能是变量(c89)。
2,scanf,gets,fgets
scanf和%s使用的时候 有个缺点 遇到 空格会结束输入
//scanf("%s",buf);//不能获取带空格的字符串
gets(buf);//获取带空格的字符串
fgets函数 既可以获取 带空格的字符串 也可以保证 buf的不越界
1 #include
2 char *fgets(char *s, int size, FILE *stream)
3 //s表示存放字符串的空间地址
4 //size 能够提取字符串的最大长度 size‐1
5 //stream stdin 表示标准输入设备
6 返回值:就是获取到的字符串的首元素地址
第三章函数
1、函数的定义:实现函数功能、确定函数体、返回值类型、形参类型。 让函数存在
2、函数的声明:不是实现函数功能 仅仅是说明改函数有返回值类型、形参类型、函数名。
3、函数的调用:函数的执行。
1、函数的定义
1 //返回值类型: 函数将来返回值的类型
2 //函数名:函数的入口地址
3 //形参:函数外部数据 传递到 函数内部的 桥梁
4 //函数体:具体的函数功能带
5 返回值类型 函数名(形参类型 形参)
6 { 函数体}
2、函数声明:
1 返回值类型 函数名(形参类型 形参);
3、函数的调用
1 //函数外部的实际数据 2 函数名(实参);
1 //函数声明:告诉编译器 该函数存在 请通过编译。
2 void my_fun();
3
4 int main(int argc,char *argv[])
5 {
6 //函数的调用:函数名+()
7 my_fun();
8 return 0;
9 }
10
11 //函数的定义
12 void my_fun()
13 {
14 printf("my fun\n");
15 return;//1、返回函数结果 2、结束函数
16 }
第四章预处理
1,内存分区
1,全局变量
2,静态局部变量
1,指针就是地址,每个字节都有对应的地址,指针变量本质就是个变量存放的是地址编号,任何地址编号都是四个字节,也就是sizeof(int * char* double ***)都是四个字节
2,如何定义一切指针
1、*修饰 指针变量名 // *p
2、保存啥类型变量的地址 就用该类型定义一个普通变量。 // int num
3、从上 往下 整体 替换 // int *p
3,*p什么意思?
*p表示取p保存的地址编号对应的空间内容。*p等价于num
4,指针变量的类型
1,指针变量自身类型(p是什么类型) 只将指针变量涂黑,剩下啥类型,指针变量自身就是啥类型。 比如 p自身的类型是int *
推广,int num,num的类型是?把num涂黑
2,指针变量所指向的类型? 将指针变量和最近的一个*一起涂黑剩下啥类型就指向啥类型 p指向的类型为int类型 == p保存int类型变量的地址
即指向XXXX类型 == 保存XXX类型变量的地址
指针变量取值宽度,指针变量取值跨度,都取决于指针变量指向的类型
5 指针变量的初始化
//如果 局部 指针变量 不初始化 保存的是随机的地址编号(千万别取值) int *p;
//不想让指针变量指向任何地方 应该初始化为NULL(千万别取值) //#define NULL ((void *)0)
int *p1 = NULL;
//将指针变量初始化为合法的地址(可以取值) int *p2=&a;
//千万别看成 *p2 = & num; 是先 int * p2; p2 = &a *修饰p2为指针变量
6,&&与**的区别
//如果对一个变量取地址 整个表达式的类型 就是变量的类型+*.
//p的类型是 int *类型
//*p的类型是 int 类型
//如果对指针变量取* 整个表达式的类型是 指针变量的类型‐*.
//高级总结:如果&和*同时存在 可以相互抵消(从右‐‐>左)。(重要)
7,数组与指针
1, []与*()关系 //在使用中 本质:[] 是*( ) 缩写
//缩写规则:+左边的值 放在[]左边边 +右边的值 放在[]里面
arr[i]=*(arr+i)
2,arr代表的是 第0个元素的地址(&arr[0])
//&arr[0] == &*(arr+0) == arr+0 == arr
//所以:数组名arr代表第0个元素的地址,&arr是数组的首地址
arr+1代表首元素地址+1,跳过了一个元素(4B)
&arr+1代表是数组的首地址+1,跳过整个数组(4*5B)
3,数组名arr是一个符号常量,不能被赋值(不能放在等号左边)
8,指针数组:本质就是数组,只是数组的每个元素都是指针
1,定义,就是数组的定义,int arr[5]
*arr
int *arr[5]
int *arr[3]={&num1,&num2,&num3} 这个数组有三个元素,每个元素是什么类型?
把arr[3]涂黑,剩下int *,每个元素是int *
2, 指针数组保存字符串
char * arr[3]={"hehe","haha","heihei"};
数组每个元素保存的是字符串首元素的地址,即arr[0]保存的是‘h’的地址
而字符串储存在文字常量区,是只读的
那如何打印字符串?
printf("%s",arr[1])
如何打印arr[1]中的字符a,printf("%c", *(arr[1]+1) )首元素的地址加一,再解引用
void test12()
{
int arr[5]={10,20,30,40,50};
int *p = arr;
printf("%d\n", *p++);//10
++运算级搞,但是因为是后自增,所以先算*p,再把p++,此时,*p=20
printf("%d\n", (*p)++);//20
先算*p就是20,然后再20++,(*p)++等价于(*p)=(*p)+1,此时*p等于21
printf("%d\n", *(p++));//21
}
9,数组指针 本质就是指针,保存的是数组的首地址,p=&arr
1,定义,就是定义一个指针,*修饰变量名*p 定义一个变量int arr [5] 替换int(*p)arr[5]
*修饰p为指针变量,指针变量保存什么类型的地址?把*p涂黑,保存的是数组的地址
是数组的地址(&arr)不是数组首元素的地址(&arr[0])
该数组有五个元素,每个元素是什么类型?
2,p=&arr,p+1跳过4*5个字节
如何利用p取出arr[3] 40?
如果p是=&arr[0]也就是p=arr,只要*(p+3),但是p=&arr故同时解引用,*p=arr
故arr[3] = *(*p+3)
睁大眼睛,*p看成*(p+0)=p[0], 见到*()想到变成p[]
*(p[0]+3)= p[0]p[3] 也就是说一维数组看成只有一行的二维数组
10,二维数组 int arr[3][4];
1,二维数组名代表行地址,加一跳过一行 arr+1就是第1行地址
2,对行地址取*就代表当前行第零列的列地址,*(arr+1)就是第一行第零列地址,再对他加一加二就可以取这一行其他元素的地址
3 ,组合技,如何取出第一行第二列的元素?
*(arr+1)第一行第零列元素地址,*(arr+1)+2,在对他解引用,*(*(arr+1)+2)
化简,== *(arr[1]+2)==arr[1][2]
4,案例, int arr[3][4]
*arr+2 第零行第二列的列地址
arr[1] 等于*(arr+1)第一行第零列的列地址
&arr[0]+2 化简==&*(arr+0)+2==arr+2第二行的行地址
**arr 化简==*(*(arr+0)+0)==arr[0][0]
11,数组指针与二维数组的关系
1,定义一个指针变量,保存二维数组的行地址 int arr[3][4]
数组指针 int (*p)[4] p=arr p完全等价与arr
2,二维数组的行数 int row = sizeof (arr)/sizeof(arr[0])
二维数组的列数 int col=sizeof(arr[0]/sizeof(arr[0][0]))
12,指针变量作为函数参数
1,如果想在函数内部修改外部变量的值,就要将外部变量的地址传递给函数(以指针变量作为函数的参数)
13,一维数组名做函数参数
1,如果函数内部想操作外部数组元素,请将外部数组的数组名传递给参数
2,一维数组作为函数的形参,会被优化为一级指针
int arr[5] int arr[]----->int *p
int arr[3][4]----->int(*p)[4]
int arr[3][4][5]------->>int(*p)[4][5]
14,函数指针
1,定义, *p int func (int a , int b)替换得到,int (*p)(int a,int b)
2,函数名代表函数入口地址,就是个地址 p=func
3,对函数指针取*****无意义
14,malloc和free函数
1 #include
2 void *malloc(unsigned int num_size);
3 形参:num_size需要申请空间大小的字节数。
4 返回值:
5 成功:返回空间的起始地址
6 失败:NULL
7 特点:
1、对于malloc的返回值 一般要强制类型转换
2、malloc申请的空间 内容不确定 一般使用memset进行清空
3、多次调用malloc 第1次malloc 和 第2次malloc的地址不一定连续
案例
void test02()
2 {
3 int *addr = NULL;
4
5 addr = (int *)malloc(sizeof(int));
6 if(addr == NULL)//申请失败了
7 {
8 printf("malloc err\n");
9 return;
10 }
11
12 printf("*addr=%d\n", *addr);//不确定的值
13
14 //对堆区空间 清0
15 memset(addr, 0, sizeof(int));
16 printf("*addr=%d\n", *addr);//0
17
18 //对addr的空间 就行写 或 读
19 *addr = 1000;//写
20
21 printf("*addr=%d\n", *addr);//1000 读
22
23
24 //释放堆区空间 空间使用权限的回收 是否对空间内容清0 这是不确定的
25 free(addr);
26 }
27 int main(int argc,char *argv[])
28 {
29 test02();
30 return 0;
31 }