C深刨7 完全搞懂 return const volatile 干货多多!!!【建议收藏!!!】

return

#include<stdio.h>
char* show(){
	char str[] = "hello world";
	return str;
}
int main(){
	char *ch = show();
	printf("%s\n", ch);
	return 0;
}

我们先看一下这个代码,这个代码是有问题的,大家可能都能知道,str数组,在show函数里面定义,是局部变量,出了作用域会销毁,所以打印乱码,但是知道这一点还是太浅显了,接下来讲一些干货!!!!!!!
**先问两个问题:

1.C语言中有字符串和字符串类型吗?

C语言中没有字符串类型但是有字符串,定义一个字符串可以利用指针,或者数组,字符串的末尾是以反斜杠0结尾,不作为字符串的一部分,只是作为一个结束标识符要明确,求字符串长度和大小是不一样的,求字符串的长度是不包含反斜杠0的,求字符串的大小是本质就是求在这字符串占用几个字节空间,所以要加上反斜杠0.

2.我们平常删除数据,比如说删除一部电影是真的在内存中删除了吗

在计算机中删除一个数据就是清空为0/1吗?
不是的,比如说:我们下载一部电影3个G,需要5分钟,但是你删除的时候,2~3秒就删除了呢
其实计算机删除数据只要把个数据,设置为无效就欧克了
,可能是通过一些协议啥的,这样设置完之后,你就可以再次利用这块空间,进行写入。

接下我们在栈帧方面解释上面那个代码

在这里插入图片描述

现在我们谈一个问题:函数调用会开辟栈帧,函数中的变量,会在栈帧中开辟空间,问题来了,你咋确保你开辟的栈帧,一定够函数中变量开辟空间用呢

解释:我们函数中变量定义肯定是有类型的这是毋庸置疑的,我们的程序没有运行之前,编译器就会根据我们的类型来预估最少开辟多大的空间,根据这个预估,编译器就会合理的开辟出我们所需要的空间
这也体现了我们关键字的作用,就是告诉编译器我需要多大的空间

经过上面的学习我们就可以理解一下递归的问题了

递归在没有出口的时候,函数就会重复的被调用,每次调用的也没释放,就会在栈空间连续的向下放,最后就会发生栈溢出

为什么临时变量具有临时性?

大家都知道了,函数调用形成栈帧,返回函数释放栈帧,C语言中的变量大部分都是在函数中定义的,就说明是局部变量,除了static修饰的。
函数调用,栈帧就开辟,该函数里的变量,就会在栈帧中开辟自己的空间,函数返回,栈帧释放,栈帧都释放了,在该栈帧中定义的变量,肯定也被释放了呗,好比,宇宙都毁灭了,还会有星球吗

言归正传继续讲解return

在这里插入图片描述
我们看着个代码,经过上面所说函数调用形成栈帧,函数返回,释放栈帧,哪这个GetData函数,为啥还可以返回x值呢???
解释:
直接查看反汇编
在这里插入图片描述
F10直接进去
在这里插入图片描述
接着返回主函数
在这里插入图片描述

从这我们可以明白,我们之前理解的没错,函数返回就是释放栈帧,x的值为啥能返回来是因为:函数的返回值是通过,寄存器的方式,返回函数调用方的!!!

------------------------------------------------------------------------------------------------
我们如果要是不接收函数的返回值会怎末样呢?
在这里插入图片描述继续反汇编
在这里插入图片描述

在返回主函数
在这里插入图片描述

总结:函数的返回值是通过寄存器的方式返回调用方的;
如果函数的返回值没有被接收的,被调函数还是会把返回值放到寄存器;

---------------------------------------------------------------------------------------------

const

在这里插入图片描述
const修饰的变量是不能直接修改的,是可以间接修改的
在这里插入图片描述
const修饰的变量可以间接的被修改,那const的意义何在呢

1,const修饰的变量,并非是,不可修改的常量
2,const修饰变量是给编译器看的,告诉编译器,这个变量是不可以修改的,如果有人修改了,你就直接报错
3,const修饰的变量是给兄弟们看的,告诉兄弟们,这个变量不要改

看一个真的不能修改的

在这里插入图片描述

如果编译器对const报错是在编译的时候报错的,不是在运行之后报错的,
const修饰变量就是给编译器看的

const修饰出数组

在这里插入图片描述
const修饰的数组,数组的每个元素都不能被修改

const修饰指针

在此我们先谈一下指针!!!

指针变量和指针是一个概念吗?

指针

简单说一下指针是什么为啥要有呢?
我们都住过宿舍,每个宿舍都有门牌号吧,这就是个标识,能告诉别人,你住在那个屋子里面。
指针也是对每个内存单元的一个标识,这样在使用这块空间的时候,才能找到。换句话说其实指针就是地址。
为啥要有指针是为了提高查找效率。如果没有指针还有遍历整个内存找数据吗?如果没有门牌号找人还要搜查整个宿舍楼吗

在这里插入图片描述
指针变量

指针变量,是变量呀,指针就是数据呀,是数据就可以被存放呀,所以指针变量就是用来存放指针相关数据的变量,在32位平台,4字节,在64位平台,8字节

在这里插入图片描述

左值与右值

在这里插入图片描述任何变量名在不同的场景中代表不同的含义!!!
指针也是一样的
在这里插入图片描述

第7行指针变量p在这代表的是p的空间,存放的是b的地址。
第8行指针变量p代表的是p空间里面的内容,即b的地址,存到指针变量q中

解引用

在这里插入图片描述

(类型相同)对指针进行解引用,代表指针所指向的目标
p指向a,解引用p,就是a!!!


言归正传const修饰指针

第一种

#include<stdio.h>
int main(){
	int a = 10;
	const int *p = &a;//const修饰*号,表示p指向的变量不可以修改
	*p = 100;
	p = 100;
	return 0;
}

第二种

#include<stdio.h>
int main(){
	int a = 10;
      int  const *p = &a;//const修饰*号,表示p指向的变量不可以修改
	*p = 100;
	p = 100;
	return 0;
}

第三种

#include<stdio.h>
int main(){
	int a = 10;
    int * const p = &a;//const修饰p,表示p的内容不能被修改,即p的指向不能被修改,只能指向a
	*p = 100;
	p = 100;
	return 0;
}

第四种

#include<stdio.h>
int main(){
	int a = 10;
    int const * const p = &a;//const修饰p,表示p的内容不能被修改,即p的指向不能被修改,只能指向a
	*p = 100;               //const修饰*,表示p指向的变量不能直接被修改
	p = 100;
	return 0;

我们再看两种情况!!!
第一种:
在这里插入图片描述
第二种:
在这里插入图片描述 ------------------------------------------------------------------------------------------

const修饰函数参数

在这里插入图片描述

void show(const	int *_p){
	printf("%d\n", *_p);
}
int main(){
	int a = 10;
	int*p = &a;
	show(p);
	return 0;
}

临时拷贝的知识点

函数调用时,会形成一份临时拷贝,那么参数要是指针变量呢,会形成临时拷贝吗?

在这里插入图片描述

答案是也会形成临时拷贝,指针变量也是变量呀,里面存放的是地址,地址也是数据呀,是数据就要形成临时拷贝呀
C中,任何函数参数都一定要形成临时变量,包括指针变量

const修饰返回值

在这里插入图片描述在这里插入图片描述

volatile

首先要明确,在没有加volatile的代码,默认会被优化,加上就不会被优化。
大概解释一下:
不加volatile

#include <stdio.h>
int pass = 1;
int main()
{
while(pass){ //思考一下,这个代码有哪些地方,编译器是可以优化的。
} 
return 0;
}

在这里插入图片描述
加volatile

#include <stdio.h>
volatile int pass = 1; //加上volatile
int main()
{
while(pass){
} 
 return 0;
}

在这里插入图片描述
结论: volatile 忽略编译器的优化,保持内存可见性
其他问题:

const volatile int a = 10;
在vs2013和gcc 4.8中都能编译通过
const是在编译期间起效果
volatile在编译期间主要影响编译器,形成不优化的代码,进而影响运行,故:编译和运行都起效果。
const要求你不要进行写入就可以。volatile意思是你读取的时候,每次都要从内存读。两者并不冲突。
虽然volatile就叫做易变关键字,但这里仅仅是描述它修饰的变量可能会变化,要编译器注意,并不是它要求对应变量必须变化!这点要特别注意

完结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值