目录
1.基础函数书写
在写一个C语言函数时,可仿照高中数学公式进行书写,
例如,设函数f(x)=3x-8,f(x)∈Z,写成函数则可为:
int f(int x)
{
return 3*x-8;
}
其中要标记,传入参数类型int,返回标记类型int,数学中的“=”相当于“return”,在计算机语言中*不可省略。
再如函数g(x,y)={f(x)+y , x>0;f(x-y+5),x<0则可写成
int g(int x,int y)
{
if(x>0)
{return f(x)+y;
}
else
{return f(x-y+5);
}
}
对于斐波那契函数,公式为:
F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
#include <stdio.h>
int f(int x)
{
if(x<2)
{return 1;
}
else
{return f(x-1)+f(x-2);
}
}
int main()
{
int k=f(5);%每次调用互相独立互不干扰
printf("%d \n",k);
return 0;
}
因为函数发生了自己对自己本身的调用,所以此函数为递归函数。对于递归函数函数的每次调用相互独立,互不干扰。直到遇到了循环终止条件(F(0)=1,F(1)=1),此时停止递归,然后一次往回赋值,直至赋值到最初要求的一个。
调用流程如下:
赋值过程如下:
2.基本数据类型的书写
#include <stdio.h>
int main()
{
//1B=1字节=8比特=8bit
//short-16bit int-32 long-64 float-32 double-64 char-8
short x1=89;
int x2=3;
long x3=345L;
float x4=15635030.56F;
double x5=35.546;
char x6='@';
int w1='#';
printf("w1=%d \n",w1);
return 0;
}
对于char型数据,‘’内可以加任何字符,如果用%d来输出,则输出其对应的ASCII值。
其中,int与float都是32bit,信息熵总量相同,两者精度无法比较,float型数据的精度为6-7位(有效数字),在小范围内精度较高,大范围内精度不高。
3.结构体的书写规则
结构体就是由基本类型组合成的复合类型。
#include <stdio.h>
typedef struct AA{
int a;
char b;
}Q;//typedef的作用相当于给结构体AA起了个新名字叫Q
typedef struct BB{
int x1;
int x2;
float x3;
}E;
int main()
{
Q x1;
struct AA x2;//此时x1和x2的数据类型一样,只是不同的两中表述方式
E x3;
struct BB x4;
printf("hello world! \n");
return 0;
}
对于代码
int a;
char b;
变量a和b在声明的时候就已经申请了一份内存空间,最初的默认值是0,但是对于结构体内部声明的变量x1.a和x1.b的初始值不是默认值0(如果内存干净的话则仍是0),而是一个随机的其他值
结构体在main函数中定义时也会申请空间,此时他申请的空间大小是根据他本身所需要的空间大小申请的,申请之后会根据其内部成员变量的大小进行切割。
存储如下:
4.指针
1. 简单int型指针变量的定义、指向、赋值
int main()
{
//指针
int a;
int* w1;//用int*来定义一个int型指针变量w1
w1=&a;//此时变量a有两个地址变量地址和数值的地址,w1指向的是a的值的地址
*w1=33;//w1所指向的区域等于33,此时a的值也会变为33
printf("a=%d \n",a);
return 0;
}
非法指向,随意自定义地址指向属于非法指向,部分编译器会进行报错
int* w2;
w2=44;//w1要指向地址为44的那块内存
*w2=55;//让刚刚指向的地址为44的那块内存数值变为55
2.结构体指针:
#include <stdio.h>
typedef struct AA{
int a;
char b;
}Q;//typedef的作用相当于给结构体AA起了个新名字叫Q
typedef struct BB{
int x1;
int x2;
float x3;
}E;
int main()
{
Q x1;
Q* w2=&x1;//用Q*来定义w2为Q类型的指针,此时w2指向x1的地址
x1.a=88;
printf("x1.a=%d,x1.b=%d \n",x1.a,x1.b);
w2->a=345;//改变x1.a的地址上的值为345
printf("x1.a=%d,x1.b=%d \n",x1.a,x1.b);//b为结构体内部声明变量,默认值为其他值
return 0;
}
对于指针变量所指区域的数值改变int型指针变量需要加上*,而结构体型则不写*
*w1=55;
w2->a=345;
对于指针变量等于指针变量(如下),表示两指针保持相同指向,w2指向w3所指向的区域
Q* w3=w2;//表示两指针保持相同指向
3.结构体指针的不同书写规则
#include <stdio.h>
typedef struct AA{
int a;
char b;
}Q,*K;//typedef的作用相当于给结构体AA起了个新名字叫Q
int main()
{
K x4;
Q* x5;//此时x4与x5为同一类型
return 0;
}
4.指针如何开辟空间
#include <stdio.h>
#include <stdlib.h>
typedef struct AA{
int a;
char b;
}Q,*K;//typedef的作用相当于给结构体AA起了个新名字叫Q
int main()
{
Q* x5=(Q*)malloc(5);
//为x5申请5个字节的空间,然后按Q的类型分为两份,1份4字节存放int,1份1字节存放char
x5->a=66;
x5->b='h';
return 0;
}
结构体外部的指针一开始是默认没有指的,所以要先申请空间,进行指向,不然会出现报错
5.指针与数组
int main()
{
int s1=90;
int* m1=&s1;//定义int型指针变量m1 指向s1的地址
int f1[]={1,2,3,4};//数组f1,自动申请4个字节的空间
int f2[3];//此时数组f2的3格式字节可能包含其他东西,因为未赋值
m1=f1;//指针指向的是数组开头第一个字节的地址
//int型指针变量m1指向数组时不需要在f1前加&,而指向int型变量s1的时候却需要(c语言的不规整性)
m1[0]=88;
m1[1]=66;
printf("m1[0]=%d",m1[0]);
return 0;
}
int型指针变量m1指向数组时不需要在f1前加&,而指向int型变量s1的时候却需要(c语言的不规整性)
6.指针相对于数组具有灵活性
#include <stdio.h>
#include <stdlib.h>
typedef struct AA{
int a;
char b;
}Q,*K;//typedef的作用相当于给结构体AA起了个新名字叫Q
int main()
{
int s1=90;
int f1[4]={1,2,3,4};
int f2[3];
Q x1,x2,x3;
Q f4[3]={x1,x2,x3};//f4[0]=x1;f4[2]=x2;f4[3]=x3;相当于直接拷贝过来,而不是指向x1,x2,x3
f4[0].a=76;
f4[0].b='w';
printf("%d,%d\n",x1.a,x2.b);
printf("%d,%d\n",f4[0].a,f4[0].b);//对f4[0]的赋值不会影响x1的数值变化
int* e1=(int*)malloc(40);//申请40个字节,分成10份(int),每份4个
e1[0]=99;
e1[1]=33;
e1=f1;//允许,此时e1指向f1,指针类型可以这样相等
//f1=f2;//不行,非指针不允许这样指向
//数组作为参数传入的时候,类型无所谓,可默认指针类型进行传入
x2=x1;//此时x1,x2都是结构体类型,可以相等,但是数组不可以这样
int f5[4][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}};
int** e2=(int**)malloc(sizeof(int*)*5);//指针类型占8字节,申请5个int型指针变量的空间
//e2里面可以容纳多个一维数组
e2[0]=e1;//长度是10
e2[1]=f1;//长度是4
e2[2]=f2;//长度是3,不需要太整齐,可以非常灵活
e2[3]=&s1;//还可以等于单个数字
return 0;
}
函数、结构体补充:
1、在函数入参位置处声明的变量和在函数内部声明的变量无任何区别。
2、对于指针等于指针,表示两个指针指向同一位置区域。
3、如果结构体嵌套自己,那其内部的那个结构体一定是指针类型,否则会出现无限嵌套的情况。结构体内部的结构体是指针类型,那么他一定只占8个字节。
4、 e3[0]和e3[1]指向的分别是e1和e2的地址,只有e3[2]指向的才是e1的值。
int e1=22,e2=55;
int* e3=(int*)malloc(sizeof(int)*3);//此时e3指向了3个int型数据
e3[0]=&e1;
e3[1]=&e2;//此时e3[1]指向了e2的地址,语法没问题,但是语句无意义
e3[2]=e1;
A* w2=(A*)malloc(sizeof(int)*3);//w2指向了3个A类型数据
w2[0]=&x1;
w2[1]=&x2;//此时w2[1]应指向A类型数据,而不能执行x2的地址(一串数字),故语法错误
w2[2]=&x2;
5、对于结构体在程序运行时的存放,
结构体信息、构造、名字等都存放在第一区域。
而结构体类型的值都存放在第三区域。
6、数组作为传入参数时按指针对待,即使传入参数格式不是指针也按指针处理。例如:
void k1(int w1[4], int* w2){//此时w1[]和w2所占字节数均为8
}
此时w1[]和w2所占字节数均为8
7、数组作为传入参数时,在传入的参数中一定要有一个size表示原数组的大小,不然传入参数按指针对待无法计算其size。
void k2(A* s2,A* s3,int s2size){
//传入参数s2带着其对应的size,说明s2一定是一个数组。而s3没有带着说明s3是一个单个的数据
}
int main()
{
k2(w2,w3,3);
}
传入参数s2带着其对应的size,说明s2一定是一个数组。而s3没有带着说明s3是一个单个的数据。