C语言(三)

目录

1,函数

1,实参,形参

2,传值调用,传址调用

区别是:

优缺点:

3,函数定义和声明

4,递归

递归的两个必要条件:

递归出错的原因:

简单介绍一下内存

5,一些代码题

1,将字符串反序输出(迭代)

2,sizeof()操作符

 3,两个字符串比大小:

4,按位取反等操作符

5,隐式转换

2,指针

1,指针和指针类型

指针类型的意义:

2,野指针

 野指针成因:

         如何避免野指针:

3,指针运算

4,指针-指针

指针-指针

例子:数组名和&数组名的区别

C语言标准的一个规定:

5,介绍一下数组中的 [ ] 符号

6,二级指针

7,指针数组

3,结构体

4,调试

常见错误分类:

调试的基本步骤:

优秀的代码:

常见的coding技巧:

debug和release的区别

  最常用的几个快捷键:

介绍一个死循环小题目:

const修饰不同位置的作用

一个很有意思的现象。

把指针赋值给指针

数据分类

5,数据的存储

浮点数的存储

浮点数在内存中的存储

重点:


1,函数

什么是函数?函数(function)是完成特定任务的独立程序代码单元。

函数组成:修饰符(可以不带),返回类型,函数名,参数列表,{ },返回值(当返回类型为void时,表示无返回值)。

举例:

static int get_max(int a, int b )					//对于get_max()来讲,a,b为形式参数
{
	if (a > b)
		return a;
	else
		return b;
}

static --- 修饰符

int     --- 返回类型

get_max --- 函数名

(int a,int b) --- 参数列表

{ }内的是函数体,内部的return 是返回值。

1,实参,形参

函数在调用的时候,实参传给形参,其实实参是形参的一份临时拷贝,改变形参不能改变实参  
 

static int get_max(int a, int b )					//对于get_max()来讲,a,b为形式参数
{
	if (a > b)
		return a;
	else
		return b;
}
int main()
{
	int x = 0, y = 0;						//在这时,对于get_max()来讲,x,y为实际参数
	scanf("%d %d", &x, &y);
	int i = get_max(x, y);
	printf("%d", i);
	return 0;
}

在main()函数中,x和y是实际参数。在get_max中,a和b是形式参数。

2,传值调用,传址调用

函数的参数列表可以既可以传递变量也可以传递指针。

区别是:

传值调用:当传递变量的时候,函数形参会在内存中复制一份实参的数值给形参,不会对原有数值造成影响。

传址调用:函数的参数列表内是指针,指向变量地址,在函数内可以直接通过指针解引用得到实参,可以在这个基础上对参数进行修改。


示例:

void exchange1(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}
void exchange2(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
int main()
{
	int x = 1, y = 2;
	printf("x = %d y = %d\n", x, y);
	exchange1(x, y);
	printf("x = %d y = %d\n", x, y);
	exchange2(&x, &y);
	printf("x = %d y = %d\n", x, y);
	return 0;
}

输出:

x = 1 y = 2
x = 1 y = 2
x = 2 y = 1

可以看到,第一次传值调用,并不会交换x,y的值;第二次传址可以成功交换

优缺点:

1,传址调用有可能会更改实参的值,传值不会修改;当在需要修改实参的时候,必须使用传址;为了防止在不需要的时候改变实参的值,我们可以在指针前加上const。

2,传址调用不需要复制一份实参,占用内存比传值调用低,效率更高。

综上:一般来讲,使用传址调用优势更加明显,当不需要更改实参时,记得加const。

3,函数定义和声明

示例:函数声明

void fun(void);

示例:函数定义

void fun(void)
{
    ;
}

 函数定义在使用之前,不会报错,假如使用在定义之前,则需要加上函数声明,否则会报错。

函数在使用之前要么声明要么定义。

 函数定义是一种更强的声明。

4,递归


递归的两个必要条件:

 1,存在限制条件,当满足这个限制条件后。递归便不再继续
  2,每次递归调用后,会越来越接近这个极限


递归出错的原因:

1,不满足两个条件;2,递归次数太多,栈溢出

简单介绍一下内存

我们需要知道内存布局是怎样的:

 内存布局分为栈区;堆区;静态区


栈区:负责存储局部变量、函数形参,调用函数时的返回值等临时变量

        在函数结束时,这些局部变量就会被销毁


 堆区:动态内存分配的malloc/free;calloc;realloc;

        直到程序结束,或者手动释放(free())才会释放内存空间


 静态区:存储全局变量;静态变量

        直到程序结束,自动释放。


每一次函数(包括main函数)调用,都要在栈区内存开辟一份空间,调用完毕,释放该内存空间,所以使用递归是需要做到两点:

        1,不能死递归,必须有跳出条件,每次递归逼近跳出条件

        2,递归层次不能太深 


递归举例:递归计算从1加到N

//递归计算从1加到N
int cal(int n)
{
	if (n == 1)
	{
		return 1;
	}
	return n+cal(n - 1);
}
int main()
{
	int i = 100;
	printf("%d\n", cal(i));
	return 0;
}

输出:

5050

不适合递归的举例:计算第N个斐波那契数 -- 1;1;2;3;5;8;13;21;34;55....

int fib(n)
{
	if (n <= 2)
	{
		return 1;
	}
	else
	{
		return fib(n - 1) + fib(n - 2);
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int z = fib(n);
	printf("%d", z);
	return 0;
}

输出:当计算第十个数时,很快就有结果了

10
55

当计算第50个数的时候,等很久都没有结果

50

这是因为

 返回值是两个数值函数,这回导致计算量指数上升,当计算第50个斐波那契数时,计算量接近2^50次。

当递归的方式,计算次数太多时,效率太低,用循环(迭代)效率比较高


修改代码:

int fib(n)
{
	int a = 1, b = 1, sum = 1;
	while (n > 2)
	{
		sum = a + b;
		a = b;
		b = sum;
		n--;
	}
	return sum;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int z = fib(n);
	printf("%d", z);
	return 0;
}

输出:

46
1836311903

5,一些代码题

1,将字符串反序输出(迭代)

void reverse_string(char * str)
{
	int len = strlen(str);
	int temp = *str;
	*str = *(str + len - 1);
	*(str + len - 1) = '\0';
	if (len > 3)
	{
		reverse_string(str + 1); 
	}
	*(str + len - 1) = temp;
}
int main()
{
	char arr[] = "abcdef";
	reverse_string(arr);
	printf("%s", arr);
	return 0;
}
输出:
fedcba

2,sizeof()操作符

sizeof(s= 2+5)  
 sizeof内部的表达式不参与运算
sizeof在编译期间运行,内部的表达式不会执行,程序执行的时候,sizeof直接计算好结果,直接输出结果4了,并不会执行内部的语句 

int main()
{
    int a = 1, b = 2, c = 3;
    char i = 1;
    printf("%zd", sizeof(i = a + b));
    printf("%d", sizeof(-i));
    return 0;
}
输出:
14


sizeof在计算字符串(字符数组)长度时,会计算“\0”;    但是strlen()在计算字符串长度是,不会计算“\0”
strlen()  函数    ---    计算字符串长度,寻找\0前出现的字符个数
sizeof    操作符---    计算(变量/类型)所占空间大小,单位是字节


 3,两个字符串比大小:


char A={"abc"}
char B={'a','b','c'}

A比B长,但是strlen的计算结果会出错,造成B看起来比A长

int main()
{
	char A[] = { "abc" };
	char B[] = { 'a','b','c' };
	char C[] = { 'a','b','c',"\0" };
	printf("%d\n", sizeof(A));
	printf("%d\n", sizeof(B));
	printf("%d\n", sizeof(C));
	printf("%d\
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值