C语言第四天

欢迎使用C语言

C作用域规则

任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域就不能被访问。C语言中有三个地方可以声明变量;
1.在函数或块内部的局部变量
2.在所有函数外部的全局变量
3.在形式参数的函数参数定义中

局部变量

在某个函数或块内的内部声明的变量称为局部变量。它们只能被该函数或该模块内部的语句使用。局部变量在函数外部是不可知的。最开始写的程序基本都是局部变量。

全部变量

全局变量是定义在函数外部,通常是在程序的顶部。全局变量在整个程序生命周期内都是有效的,在任意的函数内部能访问全局变量。
全局变量可以被任何函数访问。全局变量在声明后整个程序中都是可用的。
在程序中,局部变量和全局变量的名称可以相同,但是在函数内,如果两个名字相同,会使用局部变量值,全局变量不会被使用。

形式参数

函数的参数,形式参数,被当作该函数内的局部变量,如果与全局变量同名形式参数会优先使用。

初始化局部变量和全局变量

局部变量被定义时,系统不会对其初始化,必须自行对其变量进行初始化。定义全局变量时,系统会自动对其初始化:
int型


数据类型 初始化默认值
int 0
char ‘\0’
float 0
double 0
pointer NULL

C的形参与实参

概念:从字面上理解,所谓形式参数只是声明了一个作为参数的变量,并未直接进行赋值使用,而实际参数则相反。
Demo:

下面展示 实参与形参

#include<stdio.h>
int test(int a,int b){
    
    //形参
a=a+b;
return a;
}
int main(){
    
    
int a,b;
printf("%d",test(5,3));//实参,也赋值
}

实参可以是变量,表达式。
实参与形参类型相同或赋值兼容。
在调用函数过程中发生的实参与形参之间的数据传递 ,常称为“虚实结合”
1.在定义函数中指定的形参,在没有出现函数调用时不占用内存 中的存储单元。在函数调用时才分配内存
2.将实参的值传递给形参
3.在执行函数时,由于形参已经有值。可以用形参进行运算。
4.通过return语句将函数值返回,若无返回值,则无return
5.调用结束后,形参被释放掉,实参保留原值(单向传递)

全局变量与局部变量在内存中的区别

全局变量保存在内存的全局存储区中,占用静态的存储单元
局部变量保存在中,只有在所在函数被调用时才动态地为变量分配存储单元。

static的用法

static是C/C++中常用的修饰符,它被用来控制变量的存储方式和可见性。
程序运行结束时会自动释放,存放未初始化的全局变量和静态变量会被系统自动清0。存储在静态数据去的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。
在C++中static的内部实现机制:静态数据程成员要在程序一开始运行时就必须存在。因为函数在程序运行中被调用,所以静态数据成员不能在任何函数内分配空间和初始化。
它的空间分配有三个可能的地方:一是作为类的外部接口的头文件,那里有类声明;二是类定义的内部实现,那里有类的成员函数定义;三十应用程序的main()函数前的全局数据声明和定义处。
静态数据成员要实际地分配空间,故不能在类的声明中国定义(只能拿声明数据成员)。类声明只声明一个类的‘'尺寸和规格",并不进行实际的内存分配,所以在类声明中写成定义时错误的。它也不能在头文件中类声明的外部定义,因为会造成在多个使用该类的源文件中,对其重复定义。
static被引入已告知编译器,将变量存储在程序的静态存储区而非栈上空间,惊天数据成员按定义出现的先后顺序依次初始化,注意静态成员嵌套时,要保证所嵌套的成员已经初始化了。消除时的顺序是初始化的反顺序。
优势:
可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值时可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。

在C/C++中static的作用

(1)在修饰变量时,static修饰的静态局部变量只执行初始化一次,而且延长了局部变量的生命周期,直到程序运行结束后才释放。
(2)static修饰全局变量时,全局变量只能在本文件中访问,不能在其他文件中访问,即便是extern外部声明也不可以。
(3)static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。static修饰的变量存放在全局数据去的静态变量去,包括全局静态变量和局部静态变量,都在全局数据去分配内存。初始化时自动初始化0
(4)不想被释放时,可以使用static修饰。比如修饰函数中存放在栈空间的数组。如果不想让这个数组在函数调用结束释放可以使用static修饰。
(5)考虑到数据安全性(当程序想要使用全局变量时应先考虑使用static)。

静态变量与普通变量

静态全局变量具有特点:

(1)静态变量都在全局数据区分配内存,包括后面将要提到的静态局部变量。
(2)未经初始化的静态全局变量会被程序自动初始化为0(在函数体内声明的自动变量的值是随机的,除非它被显式初始化,而在函数体外被声明的自动变量也会被初始化为0);
(3)静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的。
优点:静态全局变量不能被其他文件所用,其它文件可以定义相同名字的变量,不会发生冲突。
(1)全局变量和全局静态变量的区别
1)全局变量时不显式用static修饰的全局变量,全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过extern全局变量名的声明 ,就可以使用全局变量。
2)全局静态变量是显式用static修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用extern声明也不能使用。

静态局部变量具有特点:

(1)该变量在全局数据区分配内存;
(2)静态局部变量在程序执行到该对象的声明时被首次初始化,即以后的函数调用不再进行初始化;
(3)静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
(4)它始终驻留在全局数据区。直到程序运行结束。但其作用于为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。
一般程序把新产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量)也存放在全局数据区。全局数据区的数据并不会因为函数的退出而释放空间。

static用法

在C++中

static关键字最基本的用法是:
1.被static修饰的变量属于类变量,可以通过类名.变量名直接引用,而不需要new出一个类来
2.被static修饰的方法属于类方法,可以通过类名.方法名直接饮用,而不需要new出一个类来

被static修饰的变量、被static修饰的方法统一属于类的静态资源,是类实例之间共享的,换言之,一处变、处处变。
在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。
惊天成员的定义或声明要加个关键static。静态成员可以通过双冒号来使用即<类名>::<静态成员名>。

静态类相关

通过类名调用静态成员函数和非静态成员函数:
(1)不能通过类名来调用类的非静态成员函数。
通过类的对象调用静态成员函数和非静态成员函数。
(2)类的对象可以使用静态成员函数和非静态成员函数。

(3)静态成员函数中不能引用非静态成员。
在类的非静态成员函数中使用类的静态成员。
(4)类的非静态成员函数可以调用用静态成员函数,但反之不能。
使用类的静态成员变量在使用前必须先初始化。
(5)类的静态成员变量必须先初始化再使用。
静态资源属于类,但是是独立于类的存在。从J类的家长在机制的角度讲,静态资源是类初始化时加载的,而非静态资源是类实例化对象时加载的。类的初始化早于类实例化对象,比如Class.forName(“xxx”)方法,就是初始化了一个类,但是并没有实例化对象,只是加载了这个类的静态资源。所以对于静态资源来说,它是不可能知道一个类中有哪些非静态资源的;但是对于非静态资源来说就不一样,由于它是实例化对象出来之后产生的,因此属于类的这些东西它都能认识。

总结

(1)静态成员函数中不能调用非静态成员。
(2)非静态成员函数中可以调用静态成员,因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。
(3)静态成员变量使用前必须先初始化(如int MyClass::m_nNumber=0;),否则会在linker时出错。
**一般总结:**再累中,static可以用来修饰静态数据成员和静态成员方法。
静态数据成员
(1)静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。
(2)静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。
(3)静态数据成员可以被初始化,但是只能在类体外进行初始化,若未对静态数据成员赋初值,则编译器会自动为其初始化为0。
(4)静态数据成员既可以通过对象名引用,也可以通过类名引用。

静态成员函数
(1)静态成员函数和静态数据成员一样,都属于类的静态成员,而不是对象成员。
(2)非静态成员函数有this指针,而静态成员函数没有this指针。
(3)静态成员函数主要用来方位静态数据成员而不能访问非静态成员。

猜你喜欢

转载自blog.csdn.net/qq_31932681/article/details/94869821