c语言基础知识(简易入门的编程思想)

本文详细介绍了C语言中的函数书写规则,包括递归函数示例,以及基本数据类型(如int、float、char)的使用。还探讨了结构体的定义与内存分配,以及指针的概念,包括简单指针、结构体指针、数组与指针的关系以及动态内存分配。
摘要由CSDN通过智能技术生成

目录

1.基础函数书写

2.基本数据类型的书写

3.结构体的书写规则

4.指针

1. 简单int型指针变量的定义、指向、赋值

2.结构体指针:

 3.结构体指针的不同书写规则

4.指针如何开辟空间

5.指针与数组

 函数、结构体补充:


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)(≥ 2,∈ 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是一个单个的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值