Bootstrap

C语言中的数组

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 一、数组的概念
  • 二、一维数组
    • 1.一维数组的定义
    • 2.数组的索引
    • 3.给一维数组的元素赋值
    • 4.输出一维数组的元素
    • 5.一维数组的地址
    • 6.代码案例:
  • 三、二维数组
    • 1.二维数组的概念:
    • 2.二维数组的内存结构图:
    • 3.二维数组的定义与初始化
    • 4.二维数组的索引
    • 5.二维数组的赋值
  • 四、一维数组与二维数组都满足交换律
  • 总结

一、数组的概念

数组就是多个类型相同的数据组合在一起。

二、一维数组

1.一维数组的定义

1.在定义时规定数组元素的个数,并且不初始化。

int a[100];

2.在定义时确定数组的元素个数,并初始化,而且初始化的元素个数要小于等于确定的元素个数。

int a[100] = {1,2,3,4,5}//{}里面的元素个数要小于等于100

3.在定义时不确定数组的元素个数,并初始化。

int a[]={100,200,300};

4.可变数组的定义:使用变量规定数组的元素的个数,并且在定义数组时不能初始化数组。

int len = 10;

int a[len];

2.数组的索引

数组的索引是从0开始一只到数组元素的个数-1(数组长度-1)结束。

3.给一维数组的元素赋值

1.直接给数组元素一个一个赋值

int a[5];

a[0] = 1;

a[1] = 2;

a[2] = 3;

a[3] = 4;

a[4] = 5;

2.使用循环给数组中的元素赋值

int a[5];

for(int i = 0; i < 5; i++){

        a[i] = i;

}

4.输出一维数组的元素

1.使用数组的下表一个一个的输出

int a[5];

printf("%d\n", a[0]);

printf("%d\n", a[1]);

printf("%d\n", a[2]);

printf("%d\n", a[3]);

printf("%d\n", a[4]);

2.使用循环遍历数组并输出

int a[5];

for(int i = 0; i < 5; i++){

        printf("%d\n", a[i]);

}

5.一维数组的地址

1.一维数组的名字可以表示该数组的首地址。

2.数组的第一个元素的地址为该数组的首地址。

3.%p为输出地址的格式控制符,&为取地址符。

int a[5];

//输出数组a的首地址

printf("%p,%p", a, &a[0]);

4.一维数组的地址可以做加减运算。

int a[5];

//输出数组a的第二个元素的地址

printf("%p\n", a+1);//首地址+1为第二个元素的地址

printf("%p\n", &a[0]+1);//首个元素的地址+1为第二个元素的地址

printf("%p\n", &a[1]);

5.* 为解引用,一般在地址的前面,作用为取地址中的内容。

int a[5];

//输出数组a的的第二个元素的值

//首地址+1为第二个元素的地址,第二个元素的地址使用解引用符号位第二个元素的值

printf("%d\n", *(a+1));

printf("%d\n", *(&a[0]+1));

6.数组长度的获取

int a[5] = {1,2,3,4,5};

//使用sizeof获取元素的个数

int len = sizeof(a) / sizeof(a[0])//数组a的整个长度/数组第一个元素的长度

7.数组名称的含义:数组名称既可以表示数组本身,也可以表示该数组的地址。

//表示数组本身

//1.sizeof计算数组所占字节数时

//2.数组定义时

//表示数组的首地址时

//1.输出数组的首地址时。

//2.使用*解引用时

//3.对首地址进行加减运算时。

6.代码案例:

#include<stdio.h>
int main(){

    //数组的概念:一群类型相同的数据组合到一起就形成了数组。
    //数组的定义:
    //1.指定数组元素的个数,并赋值,复制元素的个数小于等于指定数组元素的个数。
    int a[5] = {1,2,3,4,5};
    //2.指定数组的元素个数,不复制
    int b[5];
    //3.不指定数组元素的个数,但必须赋值。
    int c[] = {1,2,3};
    
    //数组的地址:数组的首地址为其数组名称,或者是数组第一个元素的地址
    //数组的地址是连续的,首地址即第一个元素的地址,第二个元素的地址为第一个元素的地址
    //加上单个元素的字节数,例如int类型的数组,首地址为0xfffcbc8,其第二个地址为
    //0xfffcbc8+4=0xfffcbcc,数组的地址用十六进制数表示。
    int d[] = {1,2,3};
    printf("%p\n", d);//数组的首地址
    printf("%p\n", &d[0]);//数组的第一个元素的地址即首地址。
    printf("%p\n", &d[1]);//数组的第二个元素的地址
    printf("%p\n", &d[2]);//数组的第三个元素的地址
    //数组的引用:数组下表从0开始到数组长度减一
    printf("%d\n", d[0]);
    printf("%d\n", d[1]);
    printf("%d\n", d[2]);
    //数组长度的获取
    printf("数组d的长度为%d\n", sizeof(d) / sizeof(d[0]));
    //数组名字的含义:既可以代表数组的地址,也可以代表该数组。
    //数组的赋值,不能直接给数组赋值,但可以给数组的元素赋值,数组中的每一个元素就相当于
    //该数组类型的变量。
    d[0] = 10;
    printf("%d\n", d[0]);
    d[0] = d[1];
    printf("%d\n", d[0]);

}

运行结果:

三、二维数组

1.二维数组的概念:

多个一维数组从下往上拼接而成的矩阵就是一个二维数组,可以看成是一维数组但该数组的元素也是一维数组。

2.二维数组的内存结构图:

3.二维数组的定义与初始化

1.定义时确定数组的行数与列数,不初始化

int a[10][10];

2.在定义时进行初始化操作,此时在定义时可以不写数组的行数,当必须要写数组的列数

int a[][3] = {{1,0,1},{2,1,2}};

3.在定义时进行初始化操作,并且在定义时行数与列数都写。

int a[2][3] = {{1,0,1},{2,1,2}};

4.二维数组的索引

1二维数组的索引:行从0到行元素个数-1.列从0开始到列元素个数-1

int a[2][3] = {{1,0,1},{2,1,2}};

//该数组的索引从(0,0)开始到(1,2)结束,一共2*3=6数据。

5.二维数组的赋值

int a[2][3];

//给单个元素赋值

//给第一个元素赋值

a[0][0] = 1;

//给最后一个元素赋值

a[1][2] = 5;

//循环遍历数组给数组的每一个元素赋值

for(int i = 0; i < 2; i++){

        for(int j = 0; j < 3; j++){

                scanf("%d", &a[i][j]);

        }

}

6.输出二维数组的元素的值

int a[2][3] = {{1,0,1},{2,1,2}};

//输出单个元素

printf("%d", a[0][0]);

printf("%d", a[1][2]);

//循环遍历数组给数组的每一个元素赋值

for(int i = 0; i < 2; i++){

        for(int j = 0; j < 3; j++){

                printf("%d", a[i][j]);

        }

}

7.二维数组的地址:

二维数组与一维数组,他们的名字都可以表示其首地址或收个元素的地址,其地址都可以进行加减运算,都能使用*解引用符号与&取地址符号,但不同的是二维数组是数组里面又包含了数组,就相当于地址里面又包含了地址,其地址有两层。

结构图:

int a[2][3] = {{1,0,1},{2,1,2}};

//输出数组a的首个元素的地址

printf("%p\n", a);

printf("%p\n", a[0]);

printf("%p\n", &a[0][0]);

//输出数组a的第二个元素的地址

printf("%p\n", *a+1);

printf("%p\n", a[0]+1);

printf("%p\n", &a[0][0]+1);

//使用 * 解引用符号输出第二个元素的值

printf("%d\n", *(*a+1));

printf("%d\n", *(a[0]+1));

printf("%d\n", *(&a[0][0]+1));

代码案例:

#include<stdio.h>
int main(){
    //二维数组,就是数组里又套了个数组,也可以理解为矩阵,表格。
    //二维数组的定义
    //1.定义时直接赋值
    int a[2][3] = {{1,2,3},{4,5,6}};//定义时规定行数与列数
    int b[][3] = {{10,20,30},{40,50,60}};//定义时不规定行数,只规定列数。
    //2.定义时不赋值
    int c[2][3];//行数与列数都要写。
    //单个元素输出
    printf("%d\n", a[0][0]);
    //二维数组的输出,使用嵌套for循环。
    //输出二维数组a的每个元素
    for(int i = 0; i < 2; i++){
        for(int j = 0; j < 3; j++){
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }

    //获取数组元素
    //获取二维数组a的第二个元素
    printf("%d\n", a[0][1]);
    printf("%d\n", *(&a[0][1]));
    printf("%d\n", *(a[0]+1));
    
    //获取二维数组a的第一个元素的地址
    printf("%p\n", a[0]);
    printf("%p\n", a);
    printf("%p\n", &a[0][0]);
    //输出第二个元素的地址
    printf("%p\n", *a+1);
    printf("%p\n", a[0]+1);
    printf("%p\n", &a[0][1]);
    //表示的是二维数组内第二行的数组的第一个元素的地址,不是该数组的第二个元素的地址。
    printf("%p\n", a+1);
    
    //使用双重*解引用打印二维数组元素
    //第一个元素
    printf("%d\n", *(*(a)+0));
    //第三个元素
    printf("%d\n", *(*(a)+2));
    //使用 * 解引用符号输出第二个元素的值
    printf("%d\n", *(*a+1));
    printf("%d\n", *(a[0]+1));
    printf("%d\n", *(&a[0][0]+1));
    //数组名在二维数组与一维数组的不同,二维数组中数组名a与*a指向的都是数组的首地址
    //一维数组中a指向其首地址,但*a指向的是首元素。
    //因为二维数组是有两层地址,可以理解为地址包含地址。
    printf("%p\n", a);
    printf("%p\n", *a);
}

运行结果:

四、一维数组与二维数组都满足交换律

    int num[]={10,20,30,40,50};

    printf("%d\n", num[0]);

    printf("%d\n", 0[num]);

    //上述两个结果一样。

    //解析:num[0]=>*(num+0)=>*(0+num)=>0[num]

代码:

#include<stdio.h>
int main(){
    // //数组下表满足交换律
    int num[]={10,20,30,40,50};
    printf("%d\n", num[0]);
    printf("%d\n", 0[num]);
    //上述两个结果一样。
    //解析:num[0]=>*(num+0)=>*(0+num)=>0[num]
}

运行结果:

总结

二维数组的地址理解有一定的难度,需要自己多画图,多敲代码。

;