1.数据类型
基本数据类型
整数
整型 – int 4字节
短整型 – short int 2字节
长短型 – long int 8字节
浮点数【实数】
单精度浮点数 – float 4字节
双精度浮点数 – double 8字节
字符 – char 1字节
复合数据类型
结构体
枚举
共用体
2.变量
赋给变量的数或字符最终是存放在内存中,程序终止后所占空间被释放
变量为什么要必须初始化?(初始化就是赋值)
不初始化会读取上一个程序在内存里遗留下来的垃圾数据
如何定义变量?
int i=3;等价于int i;i=3;
int i,j;等价于int i;int j;
3.单行注释 //
多行注释/* */
4 printf的用法
- printf(“字符串\n”);
- printf(“输出控制符%”,输出参数);
%d表示以十进制输出
%x或X或#X或#x表示十六进制输出(有#输出会有0x,比较好)
%o表示以八进制输出
%ld – long int
%c – char
%f-- float
%lf – double
%s – 字符串 - printf(“输出控制符1,输出控制符2”,输出参数1,输出参数2);
- printf(“输出控制符 非输出控制符”,输出参数)
printf(“i = %d”,i)//i = 为非输出控制符,保持原样输出
5.常量表示
整数
十六进制:前面加0X或0x
八进制:前面加0
浮点数
科学计数法
float x =3.2e3=3200(e表示10)
字符
单个字符用单引号或双引号
字符串用双引号
6.整数是以补码的形式转化为二进制代码存储在计算机中。
实数是以IEEE754标准转化为二进制代码存储
字符先转化成ASCⅡ码整数,与整数方式相同
7.字节是存储数据的单位,并且是硬件所能访问的最小单位。1字节=8位
8.char字符只能定义一个字符。
char ch = 'a';//正确
char ch = "a"//错误,用双引号默认添加'/0',这是两个字符。
char ch = "ab"//错误
ch = b //因为定义的是变量,所以可以重新赋值。
- scanf() 【通过键盘将数据输入变量中】
用法一:scanf(“输入控制符”,输入参数)
功能:将从键盘输入的字符转换为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中。
scanf("%d",&i)//&i 表示i的地址 &取地址
scanf(“m%d”,&i)//必须输入m数字 格式才正确
scanf不要加\n
记得变现代码对用户的非法输入做适当处理
while ((ch = getchar()) !='\n')
continue;
- 运算符
算术:+ - * / (除) %(取余)
关系:> >= < <= !=(不等于)==
逻辑:!(非) &&(与) ||(或)
&&左边的表达式为假,右边不执行
||左边的表达式为真,右边不执行
赋值:= += *= /= -=
i+=1等价于i=i+2
优先级别:算术>关系>逻辑>赋值
位运算符
1.& 位与
2.| 位或
3. ~按位取反
4. ^按位异或
5. << 按位左移 相当于乘2 补零
6. >>按位右移 相当于除2
- 流程控制
选择:if
1.if (表达式)
语句A;
语句B;
解释:if默认只能控制语句A的执行或不执行,语句B一定会实行。
2.if(表达式)
{
语句A;
语句B;此时if可以控制语句A和语句B,用大括号。
}
12.C语言对真假的处理:非零是真 零就是假
13.` for循环
for (1.(i = 1;)2.(i<=100;)4.i++)#执行顺序1234 234.4为一个循环结束
3.sum = sum + i;
- 强制类型转换
格式:(数据类型)(表达式)
功能:把表达式的值强制转换为前面所执行的数据类型
EX:(int)(4.5+2.2)=6
(float)(5)=5.00000
1/(float)(i)=1.0/i
`15.浮点数问题
float和double都不能保证可以精确的存储一个小数,故循环更新的变量不能定义成浮点型
EX:
float i = 99.9;
printf("%f\n",i);
最终输出结果是:99.900002
EX:有一个浮点型变量x,如何判断x的值是否为零
if (|x-0.000001|<0.000001)
是零
else
不是
- ++i是i加1之后的值
i++是i加1之前的值
i=j=1
m= ++i
n = i++
则m = 2,n = 1
- 三目运算符:A?B:C
等价于if (A)
B;
else
C; - 逗号表达式
格式:(A,B,C,D)
功能:从左到右执行,最终表达式为最后一项的值。
int j = 2;
int i;
i = (j++,++j,j+2,j-3);
最终i的值为1不是3!!因为j+2不等于j=j+2
- for与while转换
for(1;2;3)
A;
等价于
1;
while(2)
{
A;
3;
}
- do……while
格式: do
{
......
}while(表达式);
#与for和while不等价 因为如果表达式为假,dowhile循环会执行一次
20.scanf的一个问题
char ch;
do
{
printf("y/n\n");
scanf(" %c",&ch);%c前面必须加空格,否则会出错
}while('y' == ch);
21.switch的用法
int val;
scanf("%d",val);
switch(val)
{
case 1:
....;
break;
case 2:
....;
break;
case 3:
....;
break;
default:
...;
break;
}val的值等于几就执行哪一个,break的功能是退出switch语句,如果没有break会一直向下执行
22.break的用法
break用于循环和switch语句,不能直接用于if
for(i = 1;i<=3;i++)
{ if(3>2)
break; 这里break虽然是if内部的语句,但是是用来终止外部的循环下面的printf语句将不在执行。
printf("");
}
23.continue的用法
1.for(1;2;3)
{
A;
continue;执行完该语句后会执行3,C语句不执行
C;
}
2.while(表达式)
{
A;
continue;执行完该语句后会执行表达式,C语句不执行
C;
}
24.数组
完全初始化:
int a[3]={1,2,3}
a是数组的名字,3表示数组元素的个数,并且这三个元素分别用a[0],a[1],a[2]表示
不完全初始化:
int a[5]={1,2,3} 未被初始化的元素自动为0
不初始化:
int a[5]; 所有元素都是垃圾值
清零:
int a[5] = {0};
只有定义的时候才可以整体赋值,因为其他情况下a[i]中的i表示某个元素,而定义中i表示元素个数。
数组名代表数组第一个元素的地址
定义二维数组
int a[2][3] ={1,2,3,4,5,6};
等价于
int a[2][3] ={{1,2,3},{4,5,6}};
不存在多维数组,因为内存是线性1维的。n维数组可以当做n-1维的一维数组
25.函数`
int f(void) 括号中的void表示该函数不能接受数据,int表示函数返回值是int类型
{
return 10; 向函数返回10
}
j=f(); 若输出j,值为10
j=f(1) 错误语句
void g(void) 函数名前面的void表示该函数没有返回值
{
}
j=g() 错误语句
函数的定义
函数的返回值 函数的名字(函数的形参列表)
{
函数的执行体
}
函数返回值的类型也称为函数的类型。因为如果 函数名前的返回值类型 和 函数执行体中的return表达式中表达式的类型不同的话,则最终函数返回值的类型 以函数名前的返回值类型为准。
- return 表达式的含义
1.终止被调函数,向主调函数返回表达式的值
2.如果表达式为空,则只终止函数,不向主调函数返回任何值。
3.break是用来终止循环和switch的,return是用来终止函数的。
void f()
{
return; return只用来终止函数,不向主调函数返回任何值
}
int f()
{
return 10; 终止函数且向主调函数返回10
}
27.函数的分类
28.函数的声明
EX
void f(void); 函数声明,分号不能丢,必须加上,否则程序会报错。
int main(void)
{
f();
return 0;
}
void f(void)
{
printf("hhh");
}
4.对库函数的声明是通过# include<库函数所在的文件的·名字>来实现的
29.变量的作用域
int i=99; 全局变量
void f(int i)
{
printf("i=%d\n",i);
}
int main(void)
{
f(1);
return 0;
}
该段程序执行结果为1
int *p; 1.p是变量的名字,int* 表示p变量存放的是int类型的地址
2.int *p 不表示定义了一个名字叫做*p的变量
3.int*p应该这样理解:p是变量名,p变量的数据类型是int*类型
4.所谓int*类型 实际上就是存放int变量地址的类型
int i= 3;
p =&i;
1.p保存了i的地址,因此p指向i
2.p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值不影响p的值
3.如果一个指针变量指向了某个普通变量则
*指针变量 完全等同于 普通变量
EX:如果p是个指针变量,并且p存放了普通变量i的地址
则p指向了普通变量i
*p 完全等同于 i
或者说:在所有出现*p的地方都可以替换成i
在所有出现*i的地方都可以替换成p
*p 就是以p的内容为地址的变量
指针和指针变量的区别
指针错误
int *p;
int i=3;
*p=i; 错误
因为p内部是垃圾值,本程序不能读写*p的内容
因为此时*p所代表的内存单元的控制权限并没有分配给本程序
EX:
void f(int * i,int * j)
{
int t;
t=*i;
*i=*j;
*j=t;
}
int main()
{
int a=3,b=5;
f(a,b);
return 0;
}
函数中不用指针的话是无法修改main函数中变量的值,因为运行完函数后的内存就被清零了。
指针与数组
int a[5];
printf("%#X".&a[0]);
printf("%#X".a);
两者结果一样,说明数组名是一个指针常量,不可改变,它存放了数组第一个元素的地址
*下标和指针的关系:a[i]=P(i+1)
用函数定义数组
void f(int * a,lenth数组元素个数)
指针变量的运算
指针不能相加相乘相除
如果两个指针变量指向的是同一块连续空间中的不同存储单元,这时两个指针变量才可以相减。(即同一个数组单元可以相减)
指针变量所占字节
动态内存分配
传统数组的缺点:
malloc函数的使用
*p = 5; *p代表的就是一个int变量,只不过*p这个整型变量的内存分配方式和11行的i变量分配方式不同
free(p); 该语句表示把p所指向的内存释放掉 p本身的内存是静态的,不能由程序员手动释放,p本身的内存只能在p变量所在的函数运行终止时系统自动释放。
(int *)malloc(200) 表示200个字节分成50个整型变量
(char *)malloc(200) 表示200个字节分成200个字符变量
(double *)malloc(200) 表示200个字节分成25个双精度浮点数变量
动态构造一维数组
int len;
int * pArr;
scanf("%d",&len);
pArr = (int*)malloc(4*len);
本行动态的构造了一个一维数组,这一数组的长度是len 该一维数组名是pArr,该数组的每个元素是int类型 类似于 int pArr[len]但这是静态的
动态内存与静态内存的比较
动态内存函数结束后没有释放
结构体
1.定义
struct student 这只是定义了一个新的数据类型,并没有定义变量
{
int age;
float score;
char gender;
};
2.赋值和初始化
定义的同时可以整体赋初值
定义完之后,只能单个赋初值。
3.如何取出结构体变量每一个成员
结构体变量名.成员名
指针变量->成员名
在计算机内部会被转化为( *指针变量名).成员名的方式来执行
EX:
struct student st;
struct student * p = &st;
p->age = 44; 这两行功能相同
(*p).age = 44;
printf("%d\n",st.age);
结构体变量之间的运算
链表与数组
链表:
看懂此程序
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node * pNext;
};
struct Node * create_list(void)
{
int len,i,val;
struct Node * pHead =(struct Node*)malloc(sizeof(struct Node));
if (NULL==pHead)
{
printf("失败\n");
exit(-1);
}
struct Node * pTail = pHead;
pTail->pNext = NULL;
printf("链表节点数=");
scanf("%d",&len);
for (i=0;i<len;i++)
{
printf("请输入第%d节点的值=",i+1);
scanf("%d",&val);
struct Node *pNew =(struct Node*)malloc(sizeof(struct Node));
if (NULL==pNew)
{
printf("失败\n");
exit(-1);
}
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
};
void traverse_list(struct Node *pHead)
{
struct Node *p = pHead->pNext;
while(NULL != p)
{
printf("%d\n",p->data);
p = p->pNext;
}
return;
}
int main(void)
{
struct Node * pHead = NULL;
pHead = create_list();
traverse_list(pHead);
return 0;
}