栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

文章目录
  • return
    • 1.C语言中有字符串和字符串类型吗?
    • 2.我们平常删除数据,比如说删除一部电影是真的在内存中删除了吗
    • 接下我们在栈帧方面解释上面那个代码
    • 现在我们谈一个问题:函数调用会开辟栈帧,函数中的变量,会在栈帧中开辟空间,问题来了,你咋确保你开辟的栈帧,一定够函数中变量开辟空间用呢
    • 经过上面的学习我们就可以理解一下递归的问题了
    • 为什么临时变量具有临时性?
    • 言归正传继续讲解return
  • const
    • const修饰出数组
    • const修饰指针
      • 指针变量和指针是一个概念吗?
      • 左值与右值
      • 解引用
      • 言归正传const修饰指针
      • const修饰函数参数
      • 临时拷贝的知识点
      • const修饰返回值
  • volatile

return
#include
char* show(){
	char str[] = "hello world";
	return str;
}
int main(){
	char *ch = show();
	printf("%sn", 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
int main(){
	int a = 10;
	const int *p = &a;//const修饰*号,表示p指向的变量不可以修改
	*p = 100;
	p = 100;
	return 0;
}

第二种

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

第三种

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

第四种

#include
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("%dn", *_p);
}
int main(){
	int a = 10;
	int*p = &a;
	show(p);
	return 0;
}
临时拷贝的知识点

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

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

const修饰返回值

volatile

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

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


加volatile

#include 
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就叫做易变关键字,但这里仅仅是描述它修饰的变量可能会变化,要编译器注意,并不是它要求对应变量必须变化!这点要特别注意

完结

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/330094.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号