【C语言必备知识 2】(数组以及static详解)

目录

7.数组

7.1数组定义

7.2 数组的初始化

7.2.1 完全初识化

7.2.2 不完全初始化

7.3 数组的下标

8.static

8.1 连接属性:

8.2 连接属性分类: 

8.3 储存类型

1、auto变量:

2、register变量:

3、static变量

4、extern外部变量

8.4 static修饰 

static修饰局部变量——称为静态局部变量

2. 修饰全局变量-称为静态全局变量

3. 修饰函数-称为静态函数


7.数组

7.1数组定义

在C语言中,如果我们想要定义10个数字。你会怎么做?

#include <stdio.h>
int main()
{
    int a1 = 1;
    int a2 = 2;
    int a3 = 3;
    int a4 = 4;
    //……
    int a10 = 10;
    return 0;
}

难道是像上面的代码这样吗?如果我们这样去定义十个数字的话,效率是相当低的。C语言为我们提供了数组这一概念。数组是一个同类型元素的集合。下面来看看怎么使用他:

#include <stdio.h>
int main()
{
	//定义一个整型数组,里面存放10个数字
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	return 0;
}

小结:数组的定义可以理解为:类型+数组名字[ ],[ ]内为元素个数。

[ ]内必须为常量或者常量表达式;

#inlcude <stdio.h>
int main()
{
    //整型数组
    int arr1[3] = {1, 2, 3};

    //字符型数组(字符串)
    char arr2[3] = "hhh";
    return 0;
}

7.2 数组的初始化

7.2.1 完全初识化

将数组内的所有元素全部初始化称为完全初始化。

#include <stdio.h>
int main()
{
    //创建一个数组并将它完全初始化
    int arr[5] = {1, 2, 3, 4, 5};
    return 0;
}

我们可以在vs中通过调试打开监视窗口观察arr数组中存放的值:

000a08a3629d492bb26421c6c57caf09.png

 我们可以看到,arr数组中所有的元素就是我们创建数组时初始化的值。

注意:整个数组的初识化必须在创建数组的同时才可以。如果你想要在创建数组后再初始化整个数组。就会造成非法访问。

比如:先创建一个整型数组   int arr[3] ;

           再对arr数组进行整体的初始化 arr[3] = 0;

这样是不行的,编译器会认为你在给下标为3的元素赋值,但是arr数组中最大的下标为2;这样就造成了非法访问,编译器就会报错。

7.2.2 不完全初始化

在创建数组时,将数组中部分元素初识化称为不完全初识化。

下面我们来创建一个数组并将它的元素部分初始化:

#include <stdio.h>
int main()
{
	//创建一个数组并将它不完全初始化
	int arr[10] = { 1,2,3,4,5 };
	return 0;
}

现在我们创建了一个数组arr并初始化了它的部分元素。相信现在就有小伙伴会问了,你这个数组只初始化了部分元素,那么其他没有初识化的元素又是什么呢?

带着这样的疑问,我们再次打开调试,通过监视窗口观察arr数组中的内容:

c081479e49ca45a9a8b0fa5540839ad0.png

 我们可以看到:未初始化的元素为0。

看到这里就有人问了,你整型数组未初始化的元素为0;那么字符数组、浮点数数组呢?

下面我们再创建一个不完全初始化字符数组,去观察它里面存放了什么东西:

 2cadb3a35ace4cf292f4ced00328a944.png

我们可以看到字符数组中未初识化的元素是 '\0' 。但 '\0' 的ASCII码值是0,所以 '\0' 也是0。

小结:不完全初始化的数组中(不管什么类型的数组),没有初始化的元素都是0。

7.3 数组的下标

C语言规定:数组的每个元素都有一个下标,下标是从0开始的。 数组可以通过下标来访问的。

如果数组的元素个数为n,那么它的下标范围就是0~n - 1。


8.static

在讲解static之前,先来了解一下链接属性和储存类型。

8.1 连接属性:

链接属性与C语言中各个目标文件及函数的链接过程有关,用于认定不同文件的标识符(即程序中定义的各种名称,包括变量名、函数名)否是同一个实体。更通俗地说,就是在两个不同文件中的变量、函数声明是否指向同一个实体。比如: a、b文件同时声明了
变量c,链接属性就指定了这两处变量c是否是同一个c。
简单来说,链接属性的作用就是让你能在a文件中决定要不要访问b文件中的变量、函数。

8.2 连接属性分类: 

链接属性分为三类:外部链接(external)、内部链接(internal)、无链接(none)。

无链接(none):没有链接属性的标识符总是被当作单独的个体,也就是说该标识符的多个声明被当作不同的独立个体。如:局部变量、函数标签、函数形参等。

外部链接(external):属于外部链接属性的标识符不论声明多少次,位于几个源文件都表示同一个实体。如:没有static修饰的全局变量和函数。

内部链接(internal):属于内部连接属性的标识符在同一个源文件内所有声明都指向同一个实体,但位于不同源文件内的多个声明则分属于不同的实体。如:被static修饰的全局变量和函数。

8.3 储存类型

变量的储存类型是指存储变量值的内存类型。变量的储存类型决定了变量何时创建、何时销毁以及它的值将保存多久。

C语言中有以下几种储存类型的变量:

1、auto       自动变量             2、register     寄存器变量   

3、static     静态变量             4、extern        外部变量

1、auto变量:

在代码块中声明的变量的缺省类型是自动类型的(automatic),也就是说它存储于堆栈中称为自动(auto)变量。关键字auto就是修饰这种储存类型的,但是它极少用。因为代码块中的变量在缺省缺省情况下就是自动变量。

自动变量在程序执行到声明自动变量的代码块时,自动变量就会被创建,程序的执行流离开该代码块的时候自动变量会自行销毁。

2、register变量:

关键字register可以用于自动变量的声明,提示它们应该储存于机器的硬件储存器而不是内存中,这类变量称为寄存器变量。寄存器变量的创建时间和销毁时间与自动变量一样。

这类储存类型的变量比存在内存中的变量访问请起来效率更高。但编译器并不一定会理会register关键字,该关键字只是给编译器一个建议,他会根据实际情况判断是否将该变量储存在寄存器中。

3、static变量

在代码块中声明的变量,给他加上static后,它的储存类型会从自动变为静态。具有静态储存类型的变量在整个程序执行过程中一直存在。但是并未修改变量的作用域,它仍只能在该代码块中被访问。 

4、extern外部变量

把全局变量在其他源文件中声明成extern变量,可以扩展该全局变量的作用域至声明的那个文件,其本质作用就是对全局变量作用域的扩展。外部变量也和static变量一样,直到程序结束才会销毁。

8.4 static修饰 

 在C语言中,static是用来修饰变量和函数的:

static修饰局部变量——称为静态局部变量

下面通过一个例子来讲解:

#include <stdio.h>
void test()
{
    static int a = 0;
    ++a;
    printf("%d ", a);
}

int main()
{
    int i = 0;
    while(i<10)
    {
        test();
        i++;
    }
    return 0;
}
    

大家不妨猜猜这串代码运行的结果是什么?是输出10个1吗?我们通过vs运行看看结果:

eedb1eebeff9401490865ca9b5c1a3eb.png

 为什么输出的结果是1到10呢?通过代码我们可以发现,变量a的前面被static修饰了。

当我们的局部变量被static修饰后,前面我们讲过,局部变量属于无连接属性并且储存类型是auto。static修饰后它的储存类型从自动变量变为静态变量,但是它的链接属性和作用域并未受到影响。它的生命周期也变为整个程序的生命周期。

2. 修饰全局变量-称为静态全局变量

下面接着看一串代码:

9057cd176488488f84841a4730a8b0eb.png

  之前我们讲过,全局变量定义后可以在不同的源文件内访问。现在我们将全局变量的前面加上static看看运行结果如何:

c8a490c0e4014d4f8552c07329552080.png

 我们可以看到,编译器给我们报了一个错误,说是有一个无法解析的外部命令。

当我们的全局变量的声明前加上static后,static改变了它的连接属性(从external变为internal),但该变量的储存类型不会受影响。这使得全局变量只能在他所在的源文件内不能被访问到。

3. 修饰函数-称为静态函数

当static修饰函数后,会跟全局变量一样,连接属性从外部链接属性变为内部链接属性,函数只能在自己所在的源文件中才能被访问到。

猜你喜欢

转载自blog.csdn.net/m0_74459723/article/details/127468281