c语言概述及复习
0.建立解决方案
先在新建中找到,其他项目类型-vs解决方案-空白解决方案-可以打开视图看列表-.sln文件里包含所有的工程-右键解决方案-新建一个控制台应用-想要运行哪个项目 就右键将其设为启动项
1.类型
内置类型:char short int long float double (没有string类型!!!)
自定义类型:指针 数组 结构体 联合体 枚举类型
类型的隐式转化:不同类型之间如果进行计算
char a=256; //有符号char类型 0 255是顶峰 转了一圈又到了0 //255是全1 即为-1
short b=1;
a+b=? //a+b=1;
类型隐式转化规则
double<—float
^
unsigned
^
long
^
int <-------short,char,unsigned char,unsigned short
2.变量和表达式
声明一个变量
初始化变量
给变量赋值
需要分清这三个的区别
运算符: 运算符的优先级比较重要!!
3.判断语句
if(){}
else if()
else
switch(整型值){
case 标签:{break;}
default:}
4.循环
for(表达式1;表达式2;表达式3)
while(条件)
do{}while() 比while多循环了一次
break和continue break是结束整个循环 continue是结束当前循环,直接进入到下一次循环
5.指针
一级指针(指定变量:存储一个变量的地址)
int a=10;
int *p=&a;
printf("%d",p); -->a的地址
printf("%d,*p); —>a的值
二级指针: 存储的是指针变量的地址
int a=10;
int *p=&a;
int **q=&p;
printf("%d",q); -->p的地址
printf("%d,*q); —>p的值,即a的地址
printf("%d,**q); —>a的值
6.函数
1.函数声明:给定函数的返回值类型 函数名 形参列表
2.函数定义:加了个函数体
3.函数调用:函数名(实参列表)
4.函数的参数:值传递和地址传递
1.值传递
形参类型和实参类型相同,形参是实参的副本。
形参的改变不会改变实参的值
2.地址传递
兴参事室参类型的指针,形参保存的是实参的地址。
形参的改变可以改变实参的值
地址传递的使用场景: 需要在一个函数中修改实参的值时
提高效率(结构体)
5.函数的返回值
值返回:没有特别要注意的
地址返回:不能返回局部变量的地址
全局变量 静态变量(静态全局 静态局部)
==static静态关键字 ==添加到函数之前:限制函数的访问作用域,只能被本文件中的其他函数调用
添加到变量之前:
全局:限制其访问作用域,只能在本文件中使用
局部:扩展其生存周期,变量定义的语句只会被执行一次
void fun(){
static int a=10; //只会在第一次调用时,执行一次 之后都只会进行++
a++;
printf("a=%d\n",a);
}
int main(){
fun(); //11
fun(); //12
fun(); //13
return 0;
}
6.函数指针
typedef void(*Fun)(int ,int); //把返回值为两个int类型的函数 重命名为fun
void add(int a,int b);
Fun fun=add;
使用场景: 将函数作为参数传递给另一个函数
//类似多态的一种操作
typedef int(*Fun)(int ,int);
int calc(int a,int b,Fun fun){
return fun(a,b);
}
int add(int a,int b){
return a+b;
}
int calc(int a,int b){
return a-b;
}
int main(){
printf("%d\n",calc(10,3,add));
printf("%d\n",calc(10,3,sub));
return 0;
}
7.数组
1.一维数组:同种类型变量的集合
int arr[5]={1,2,3,4,5};
10 // 1 2 3 4 5 0 0 0 0 0
printf("%d",arr[2]); //下标是从0开始,到len-1结束
printf("%d",*(arr+2));
printf("%d",size(arr)); //20
arr+1(跑一个元素,跑4个字节) &arr+1(跑整个数组,跑20个字节) &arr+2(40个字节)
int main(){
printf("%x\n",&arr);
printf("%x\n",&arr+1); //相差了20
}
2.二维数组:是一个一维数组,其中每个元素又是一个一维数组
int arr[3][4];
0 1 2 3
arr[0]
arr[1]
arr[2]
printf("%d\n",arr[1][2]);
printf("%d\n",*(arr[1]+2));
printf("%d\n",*(*(arr+1)+2));
3.指针与数组
指向一维数组的指针:
int arr[5];
int *prr=arr;
指向二维数组的指针:
int arr[3][4];
int (*prr)[4]=arr; // 括号先进行运算 因此是一个指针
指针数组:存储指针的数组:
int * prr[5]={数据是地址}; //没有括号 因此从右向左先是一个数组 然后类型是指针 因此是指针数组
4.函数与数组:给函数传递一个数组
数组名在函数传递过程中,形参部分不退化为指针!!
int arr[5]; //sizeof(arr) =20
fun(arr); --->fun(int *p) //sizeof(p) =4
8.结构体
自定义类型:过程抽象实体的属性,在计算机中抽象出实体的类型
struct Node{
属性 1; //内置类型或者可以是其他的自定义类型
属性 2;
属性 3;
}
1.结构体变量的访问
struct Node{
int a;
char b;
};
struct Node node={10,'a'};
node.a;
node.b; //成员访问符
struct Node *p=&node;
p->a; (*p).a
p->b; (*p).b 指向符
2.结构体的字节对齐问题 设计数据结构的节点类型
//字节大小为:12
struct Node{
char a;
int b;
char c;
};
//字节大小为:8
struct Node{
int b;
char a;
char c;
};
//字节大小为:8
struct Node{
char a;
char c;
int b;
};
联合体:在使用的时候只能用一个值 共用的是一个同一块内存 比如下面的程序 只要满足int类型4字节就可以了
union Node{
char a;
char c;
int b;
};
9.时间复杂度和空间复杂度
时间复杂度
时间复杂度:运行算法的工作量与问题规模之间的函数关系
选择一个关于研究问题的最基本的原操作,该操作重复执行的次数(与问题规模相关)
1.略去常数
2.去掉系数
3.取最高项
void fun(int n) -->O(n)
{
for(int i=0;i<n;++i) 如果把++i变成i+=2也是 O(n)
{
...
...
}
}
void fun(int n) -->O(n²)
{
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
...
...
}
}
}
void fun(int n) -->O(log2(n)) // 2^x=n x=log(n)
{
for(int i=0;i<n;i*=2)
{
...
...
}
}
void fun(int n) -->O(nlog2(n))
{
for(int i=0;i<n;++i)
{
fun(n);
...
...
}
}
空间复杂度:算法需要的额外的辅助空间与问题规模的函数关系。
1.int i , j, k ,m; ------>O(1)
2.malloc() ------->与问题规模n之间的关系
3.递归次数与问题规模n之间的关系 ----->函数栈帧的开辟