【C语言学习】C语言中的函数

代码中,函数是为了更好的实现模块化的程序设计。那么函数的本质是什么?函数中定义的变量(全局变量、局部变量、静态变量等)又是怎样存储的?为什么全局变量与局部变量的作用域和生命期不相同?只有更加深入的了解函数,才能解答这些问题!

★函数的本质

函数的本质是一段可执行的机器指令代码,函数名的本质是一个标号,表示函数代码的入口。该标号的值等于内存中存储函数代码的内存空间的首地址。

★变量

●全局变量

全局变量也就是外部变量,定义在函数的外部。因此它不属于任何一个函数,只属于所在的源文件。

▲初始化

对于全局变量来说,如果没有被初始化,其值由编译器自动设置为0。因此,使用一个全局变量不用考虑它的初始化问题。

运行结果:

▲作用域和生命周期

其作用域从定义该变量的这一行开始到定义该变量的源文件结束,在此期间,所有的函数都可以引用该变量。这里有一点要注意:全局变量作用域的范围并不是从程序的开始一直到程序的结尾,而是从定义这个变量的开始处到程序的结尾。

有这样一种情况:在一个源文件中,定义全局变量之前已经定义了一个函数A,那么A就不能引用这个全局变量。如果非要引用这个变量,那么就先在A之前声明这个全局变量。

●局部变量

局部变量也成为内部变量,它定义在函数或者复合语句的内部。

▲初始化

如果局部变量未被初始化,那么直接引用会很危险。因为局部变量存储于内存的堆栈中。定义了局部变量之后,编译器不会将其初始化为0,而是此内存空间原来的值。那么这个值是一个随机值,最后就可想而知了。因此,局部变量一定要记得初始化!

运行结果:

▲作用域和生命周期

因为它定义在函数内部或者复合语句的内部。因此,其作用域仅限于函数或者符合语句内。

★变量存储

源文件中,不同的变量存储在不同的区域内。一个程序在运行期间会占用内存,并且内存的使用情况也不同。一般会分为:数据段、代码段、堆栈段、BSS段

●BBS段(Block Started by Symbol)

通常用来存储未初始化全局变量和静态变量的一块区域。BSS段属于静态内存分配。在程序执行之前,BSS段会自动清零。这也就是前面全局变量不用初始化的原因。

●代码段

用来存放程序的执行代码。这段内存在程序运行之前就已经确定。

●数据段

通常用来存放已经初始化的全局变量和静态变量。属于静态内存分配。

●堆

用来存放程序动态分配的内存空间,大小不固定。可扩张、可缩减。当调用malloc函数时,就是从堆上分配内存,内存空间扩大;调用free函数时,堆上内存空间就会缩减。

●栈

用来存放函数内部定义的局部变量(注意:不包括static声明的变量,一般存储在数据段中)。在函数被调用时,其参数也会被压入发起调用的堆栈中,并且待到调用结束后,函数的返回值也会被放会栈中,由于栈的先进后出的特点,所以栈特别方便用来保存/恢复调用现场,从这个意义来讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

★函数有关的优化

●函数调用优化

函数的作用是使代码模块行增强,有利于代码的阅读和修改,可以有效的缩减代码的体积。但是函数调用是很费时的,一个函数调用一般有4步:

1、需将参数压入堆栈

2、需要保存寄存器的值

3、需要保存返回地址

4、会造成跳转

这四步中以上3步都需要访问内存。访问内存是很消耗时间的,如果程序中调用函数过多,其运行的速度肯定会很慢。因此在程序执行过程中,应该尽量减少不必要的函数调用,这样才能提高程序的执行速度。

●变量存储优化

由于局部变量存储在栈上,全局变量存储在数据段上。由于两者的存储位置不同导致生命周期的不同。

对于程序中调用很高的局部变量,编译器会自动将其存储在寄存器中,但是全局变量不会被存储在寄存器中。因为全局变量在整个程序中一直存在,如果全局变量存储在寄存器中,那么寄存器就无法存储临时变量或者中间值。计算机中,寄存器资源本来就稀少,程序的运行效率也没有效率。因此,全局变量一定要存储在数据段上,也就是内存中。尽量减少内存的访问也是提高程序执行速度的方法!(寄存器位于CPU中,它的特点是:容量小,速度快。如果一些变量被频繁的使用,就将此变量存储于寄存器中。这样就会减少对内存的频繁操作,从而节约了时间)

【C语言学习】C语言中的函数

时间: 2024-12-28 15:25:45

【C语言学习】C语言中的函数的相关文章

C语言学习second--C语言基础学习

1.标准C语言 C语言诞生于20世纪70年代,年龄比我们自己还要大,期间产生了很多标准,但是各种编译器对标准的支持不尽相同. ANSI C是使用的最广泛的一个标准,也是第一个正式标准,被称为“标准C语言”.ANSI C于1980年由美国国家标准局(American National Standards Institute,简称ANSI)对外发布,各种编译器几乎都完整支持ANSI C,市面上的书籍.大学里的教材.网上的教程大都以ANSI C为基础进行讲解,C语言中文网也不例外,也以ANSI C为基

Linux系统下C语言如何调用scalapack中的函数

在并行计算中经常需要调用scalapck(并行化的lapack)函数库里面的函数进行编程,这里简单介绍在C语言如何调用scalapck中的矩阵向量乘的函数. 注意:scalapack中的函数是用fortran写的,矩阵是按列进行存储的. scalapack的链接需要用到blas,因此确保本机上安装好了blas.gfortran 下面是一个矩阵向量乘法的例子(为了简单计算,该程序中设定进程数为4): #include <stdio.h> #include <string.h> #in

C语言学习笔记---好用的函数memcpy与memset

这个主要用于我个人的学习笔记,便于以后查询,顺便分享给大家. 想必在用C的时候难免会与数组,指针,内存这几样东西打交道,先以数组为例,例如有一个数组int a[5] = {1, 2, 3, 4, 5},我们要将数组a里面的数据复制到数组b中,一般刚刚接触C语言的我们会怎么做?我们一般会想到用循环来做吧 1 int i; 2 int a[5] = {1, 2, 3, 4, 5}, b[5]; 3 4 for(i = 0; i < 5; i++) 5 { 6 b[i] = a[i]; 7 } 但是,

C语言学习入门 (七) 变量与函数,static和extern关键字

局部变量 1> 定义:在函数内部定义的变量,称为局部变量.形式参数也属于局部变量. 2> 作用域:局部变量只在定义它的函数内部有效,即局部变量只有在定义它的函数内部使用,其它函数不能使用它. 全局变量 1> 定义:在所有函数外部定义的变量,称为全局变量. 2> 作用域:全局变量的作用范围是从定义变量的位置开始到源程序结束,即全局变量可以被在其定义位置之后的其它函数所共享. 变量的存储类型 C语言根据变量的存储类型(变量存储的位置:1. 运行时堆栈 2.普通内存 3.寄存器)的不同,

C语言学习第9天:函数(二)

局部变量 局部变量也成内部变量,在函数内部使用,不能被该函数外的代码使用 函数调用结束后,局部变量所占的内存自动释放 局部变量应该尽量定义在程序块的开头 全局变量 如果不初始化自动清0,局部变量如果不初始化会产生随机值: 对整个程序都是可见的 他不属于某个函数,而属于整个源文件 一般在main()函数之前声明全局变量 如不初始化,系统自动初始化为0 静态局部变量 只被初始化一次,在第一次进入函数时创建,退出函数时保留其值: 静态局部变量和全局变量一样,系统默认初始化为0: 函数与数组 1.数组元

C语言学习第9天:函数(一)

一.函数的作用 将一些大的或者功能相同的程序分割成一个个程序块,这些独立的模块就可称为函数. 1.函数是构成程序的基本单元 2.函数的使用可以省去重复代码的编写: 3.函数使得程序更加模块化,提高程序的可阅读性: 二.函数的分类 1.库函数.用户自定义函数 库函数是系统已为开发者提供的一些现成的函数,用户可以直接拿过来使用的: 用户自定义函数是用户为实现某些特定功能,而自己编写的代码段: 2.返回值类型.无返回值类型 有返回值函数:此类函数被调用执行完毕后将相调用者返回一个执行结果,称为函数返回

C语言学习笔记 (010) - 编写strcpy函数

很多公司的面试官在面试程序员的时候,要求应聘者写出库函数strcpy()的工作方式或者叫实现,很多人以为这个题目很简单,实则不然,别看这么一个小小的函数,它可以从三个方面来考查: (1)编程风格 (2)出错处理 (3)算法复杂度分析(用于提高性能) 最好的写法如下: 代码如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <assert.h> 4 5 //链式访问 6 char * my_strcpy(ch

大数据学习之Scala中main函数的分析以及基本规则(2)

一.main函数的分析 首先来看我们在上一节最后看到的这个程序,我们先来简单的分析一下.有助于后面的学习 object HelloScala { def main(args: Array[String]): Unit = { println("I Love You Scala"); } } 如图所看到的,在Scala中能够使用object和class分别定义一个类.两者还是存在一些区别.以后我会在专门的博客中给予介绍. 在Scala中定义一个函数使用:def 来修饰 完整定义一个函数为

深度学习计算模型中“门函数(Gating Function)”的作用

/* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/ author: 张俊林 看深度学习文献,门函数基本上已经是你必然会遇到的一个概念了,最典型的就是LSTM,首先上来你就得过得去"遗忘门""输入门""输出门"这三个门.门函数本身是个独立概念,不过LSTM使用多个门函数来组合出一个带有状态记忆的计算模型而已.随着LSTM大行其道,各种计算模型开始在计算过程中引入门函数的概念,相信这些论文你也没少看,其实这也是一种研究模式,比如

SQL语言学习-数据操纵语言

一般而言,数据库中数据的生命周期包括数据插入以及更新.数据删除3个阶段.首先需要用户或者系统将数据插入表.然后,对数据的使用,包括数据的检索以及数据的更新.最后,如果数据已经没有使用价值,则将数据删除.DML就是在数据的生命周期中用于数据操纵命令的集合. 在DML中,使用Insert将数据插入表中,使用select检索数据,使用update更新数据,使用delete命令实现对数据的删除. 1.数据插入命令 insert into table_name(col_name)values(value)