数组小结

这篇博客总结了数组的基础知识,包括数组的定义、创建方式、初始化、内存存储方式以及一维和二维数组的特性和指针访问。讲解了数组的下标从0开始,内存中连续存放,以及如何通过指针访问数组元素。还提到了二维数组的创建和内存存储形式。

这次我们来简单对数组的知识做一个小结。

数组的定义:

数组是一组相同类型元素的集合。

数组的创建方式:

<数组类型> 数组名[数组大小]

我们来建立一个数组来举一个例子,如下:

#include <stdio.h>
int main()
{
   int arr1[10];
   char arr2[5];
   int arr3[3+3];
   char arr4[10]; 
   double arr5[20];

    return 0;
   }

以上创建的数组都是合法的。在数组的创建中,数组类型可以是任意数据类型,而[ ]中的常量可以是一个表达式,但是绝对不可以是变量

数组初始

数组创建过程中给数组初始值,即初始化
如下:

int arr[5]={1,2,3,4,5};
int arr2[]={1,2,3};
char arr3[4]={'a','b','c'};
char arr4[5]="abcdef";

特别的:
1.如果数组不想指定大小,那么就得初始化,这时候数组的大小就由数组初始化的内容来决定,比如数组arr2。
2.如果数组大小已经确定,但并未给数组初始值或者初始值个数小于数组大小,那么剩余空间的初始值默认为零。当然了,初始值的个数大于数组大小也是不可以的。

区别不同的数组存储
char arr1[]="abcd"char arr2[]={'a','b','c','d'};

char* p="abcde";

数组arr1中的元素是5个,在数组开辟的内存块中存储内容为’a’,’b’,’c’,’d’,’\0’。
数组arr2中的元素是4个,数组开辟的内存块中存储内容为’a’,’b’,’c’,’d’。
第三种写法中,也能够打印出字符abcde,p只存放’a’的地址。

特别的:数组arr2在输出时,’\0’是字符数组的结束标志,如果没有’\0’,那么数组在输出时会因为找不到结束标志出现乱码。

一维数组

之前在操作符里面介绍过[ ]下标操作符,其实它就是一个数组访问的操作符。

1.数组是使用下标来访问的,并且下标是从0开始的。
2.数组的大小可以通过计算得到

int arr[5];
int size=sizeof(arr)/sizeof(arr[0]);
一维数组的存储方式

通过下面一段代码

#include <stdio.h>
int main()
{
    int a[10] = { 0 };
    int i = 0;
    for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("&a[%d]=%p\n", i, &a[i]);
    }
    return 0;
}

我们可以看到数组每个元素的地址,如下图
这里写图片描述
我们发现每个元素的地址之间相差4个字节,并且地址是连续的一段。
所以我们可以得到一个结论:
数组在内存中是连续存放的,并且存储方式由低地址向高地址的

就像这样
这里写图片描述

值得注意的是
&a[i]与p+i所表示的意义是完全相同的,都是表示第i各元素的地址,p中存储的是数组首元素的地址,所以p加i就为第i个元素的地址。。
代码证明如下:

#include <stdio.h>
int main()
{
    int a[10] = { 0 };
    int i = 0;
    int *p = a;
    for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("&a[%d]=%p <====> %p\n", i, &a[i],p+i);
    }
    return 0;
}

结果如图:
这里写图片描述

根据数组在内存中连续存放的特点,我们可以发现数组不仅可以用下标访问,也可以用指针来访问。
以下两段代码都可以实现对数组元素的访问:

#include <stdio.h>
int main()
{
    int a[10] = { 0 };
    int i = 0;
    int *p = a;
    for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        a[i]=i;
    }
    for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("%d ", a[i]);
    }
    return 0;
}
#include <stdio.h>
int main()
{
    int a[10] = { 0 };
    int i = 0;
    int *p = a;
    for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        *(p+i)=i;
    }
    for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("%d ", a[i]);
    }
    return 0;
}

结果都相同
这里写图片描述

既然可以用指针访问,那我们就来介绍一下指针。
内存中的一个内存单元(或者说字节)对应一个地址,我们想要拿出某个变量的地址,就需要借助指针,指针是一个专门用来存放地址的变量,指针在32位机器上指针变量的大小是4个字节,而64位机器上指针的大小是8个字节。
当我们拿到指针的时候,也要能够找的指针所指向的变量。这里就借助到了*(解引用操作符)了。

int n=2;
int *p=&n;//这里就表示将n的地址存放在指针变量p中
*p=3;//实际上改变的是n的值 
一维数组数组的指针访问

通过下面一段代码,

#include <stdio.h>
int main()
{
    int a[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
    printf("%p\n", a);
    printf("%d\n", *a);
    return 0;
}

输出结果:
这里写图片描述

我们会惊喜的发现,数组的数组名其实是数组首元素的地址。

那么访问数组的其他元素我们就可以酱紫:

#include <stdio.h>
int main()
{
    int a[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
    int i = 0;
    int *p = a;
    for (i = 0; i < sizeof(a) / sizeof(a[0]);i++)
    {
        *(p + i) = i;

    }
    for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("%d --- %p\n", *(p + i), (p + i));
    }
    return 0;
}

结果如下:
这里写图片描述

二维数组

二维数组的创建与初始化

int arr1[3][4]={1,2,3,4,5};
int arr2[3][3]={{1,3},{2,4}};
int arr3[][4]={{1,2},{1,4}};

特别的:二维数组创建时,行数可以为空,但是列一定不能为空。

二维数组在内存中的存储

我们先来打印一个二维数组的地址

#include <stdio.h>
int main()
{
    int arr1[3][3];
    int i = 0;
    int j = 0;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("&arr[%d][%d] ---> %p\n", i,j,&arr1[i][j]);
        }
    }
    return 0;
}

结果如下:

这里写图片描述

通过数组各个元素的地址我们发现,二维数组在内存中也是连续存放的。

这里写图片描述

同一维数组一样,有了连续存储这个前提条件,二维数组也可以用指针来访问
像这样:

#include <stdio.h>
int main()
{
    int arr1[3][3];
    int *p = &arr1[0][0];
    int i = 0;
    int j = 0;
    for (i = 0; i < 3 * 3; i++)
    {
        *(p + i) = i;
    }
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", arr1[i][j]);
        }
    }
    return 0;
}

运行结果

这里写图片描述

关于数组的运算

一维数组

#include <stdio.h>
int main()
{
    int a[] = {1,2,3,4};
    printf("%d\n", sizeof(a));//16   表示数组总长度
    printf("%d\n", sizeof(a+0));//4  表示下标为零的元素
    printf("%d\n", sizeof(*a));//4  表示数组首元素
    printf("%d\n", sizeof(a+1));//4  表示下标为1的数组元素的地址
    printf("%d\n", sizeof(a[1]));//4  表示下标为1的数组元素
    printf("%d\n", sizeof(*&a));//16  表示数组的总长度,*是对地址的解引用操作,所以等同于第一个
    printf("%d\n", sizeof(*a));//4  表示数组的地址,特别注意,地址都是4个字节
    printf("%d\n", sizeof(&a+1));//4  跳过整个数组的下一个地址 
    printf("%d\n", sizeof(&a[0]));//4  首元素的地址
    printf("%d\n", sizeof(&a[0]+1));//4  下标为1的元素地址
    return 0;
}

sizeof(数组名)—->数组名表示整个数组,计算的是数组的总大小。
&数组名—->数组名表示整个数组。
&数组名—->取出的是数组地址。

除此之外,所有数组名都表示首元素的地址。

#include <stdio.h>
int main()
{
    char a[] = {'a','b','c','d','e','f'};
    printf("%d\n", sizeof(a));//6  数组总长度
    printf("%d\n", sizeof(a+0));//4  首元素地址,即使是字符的地址,也一样是四个字节
    printf("%d\n", sizeof(*a));//1   首元素
    printf("%d\n", sizeof(a[1]));//1  
    printf("%d\n", sizeof(&a));//4  数组地址
    printf("%d\n", sizeof(&a+1));//4  跳过数组的地址
    printf("%d\n", sizeof(&a[0]+1));//4  第一个元素的地址
    return 0;
}

好啦,今天就写这些啦,如果有不足之处还请大家多多指正,^-^

好的,我可以为您总结一下Numpy数组与矩阵运算实验的内容。 Numpy是Python中用于科学计算的一个重要的库,它提供了高性能的多数组对象以及各种计算和操作这些数组的函数。Numpy数组与矩阵运算实验主要包括以下内容: 1. Numpy数组的创建与索引:可以使用Numpy提供的array()函数创建一或多数组,并且可以使用索引和切片来访问数组中的元素。 2. Numpy数组的基本运算:Numpy提供了基本的数组运算,包括加、减、乘、除等,可以对数组进行逐元素的运算。 3. Numpy数组的聚合运算:Numpy提供了一些常用的聚合函数,比如sum()、min()、max()、mean()等,可以对数组中的元素进行聚合运算。 4. Numpy数组的逻辑运算:Numpy提供了逻辑运算符,可用于数组中元素的逻辑判断,如and、or等。 5. 矩阵的创建与运算:Numpy提供了矩阵对象,可使用matrix()函数创建矩阵,矩阵之间的运算包括加、减、乘、转置等。 6. 广播:Numpy提供了广播功能,可以使得不同形状的数组在运算时具有相同的形状。 通过实验练习,可以掌握Numpy数组与矩阵运算的基本操作,如数组创建、索引、运算、聚合、逻辑运算以及矩阵创建、运算、转置等。同时,实验也会涉及到一些高级的Numpy应用,比如随机数生成、线性代数运算、数组的拼接、切分和重塑等,这些内容需要结合实际应用场景进行练习。 总的来说,Numpy数组与矩阵运算实验是Python科学计算中非常重要的部分,需要反复练习和实践,才能掌握这些知识点并灵活运用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值