数组·学习整合

目录

一、深入浅出数组

二、二维数组的数组名作用

三、再谈数组名的作用

四、数组指针变量的应用场景

五、指针数组


一、深入浅出数组

1、数组的认知:
    a.静态分配空间(int a[100];400个字节)-->空间利用率差(不够用、浪费空间)
    b.所占内存空间特点:连续的(物理连续)-->malloc分配空间是否连续?不一定连续,链表连接所有空闲的空间,组成最终分配的空间
2、如何使用数组
    a.定义数组:数组应该定义多大?char src[1024];-->柔性数组!!!
    注意事项:可变长数组C99
    C89:定义数组时,必须确定长度;(选择方式)-->通常使用宏的方式定义数组,使用后,一方面可以快速更改数组大小,另一方面可以加强可读性。
    b.数组使用:
    数组名的作用:
    一维数组名:指针常量(元素类型的指针),保存的数组首元素的地址;
#include <stdio.h>
​
struct node
{
    int len;
    //char ch;
    int array[0];//没有占用空间
};
​
int main(int argc, char const *argv[])
{
    //c99:可变长数组:可以用变量来定义数组的长度
    //注意事项:不能使用过程中已修改变量的值,来扩充数组的内存空间;
    //柔性数组
​
    printf("sizeof(struct node) = %ld\n",sizeof(struct node));
​
    struct node n;
    n.len = 10;
    n.array = (int*)malloc(sizeof(int) * n.len);
​
    int n; //局部变量--展空间--为初始化的变量自动赋值随机值; -122
​
    int a[n];
​
    int a1[0];
​
    printf("Please input n:\n");
    scanf("%d",&n);
​
    for(int i = 0; i < n;i++)
    {
        a[i] = i + 1;
    }
​
    for(int i = 0; i < n;i++)
    {
        printf("a[%d] = %d\n",i,a[i]);
    }
    //n = 10;
    //这个设置n的方法比没有解决我们的问题
​
    return 0;
}
//数组名的作用
#include <stdio.h>
​
void func(char src[100])//退化指针:char *src-->所以为sizeof(src) = 8
{
    printf("sizeof(src) = %ld\n",sizeof(src));
    src++;
}
​
int main(int argc, char const *argv[])
{
    int a[3] = {0};//局部数组
    char buffer[1024] = "hello world";
​
    func(buffer);//值没有改变
    printf("%c\n",buffer[1]);
    printf("%c\n",*(buffer + 1));
​
    int *p = a;//p指向数组首元素 p == a
​
    // memset(a,0,sizeof(a));
​
    for(int i = 0;i < sizeof(a)/sizeof(int);i++)
    {
        //方法一
        //scanf("%d",&a[i]);
        //方法二:数组名:数组首元素的地址
        //scanf("%d",a+i);
        //方法三:用其他指针指向
        scanf("%d",p++);
​
        //这样不可以,数组名是一个指针常量,保存的是首地址数组
        //scanf("%d",a++);
    }
​
    //这里如果不重新指向,就是指向数组范围外,为野指针
    p = a;
​
    for(int i = 0;i < sizeof(a)/sizeof(int);i++)
    {
        printf("a[%d] = %d\n",i,*(p + i));
    }
    return 0;
}

二、二维数组的数组名作用

二维数组名:指针常量(一维数组指针),保存首个一维数组的地址;
//二维数组
#include <stdio.h>
​
int main(int argc, char const *argv[])
{
    //方法一
    int aa[2][2];//-->两个int a[2]一位数组构成
    //方法二:不可以省略列,但可以省略行
    //int aa[][2] = {1,2,3,4};
​
    //错误写法
    //int aa[][] = {1,2,3,4};
​
    /**
     * 二维数组
     * aa:指针常量,保存的是首个一维数组的地址;
     * &aa:二维数组的地址
     * *(&aa) = aa:对二维数组的地址取值等于首个一维数组的地址
     * *aa:首个一维数组的首个元素的地址
     */
​
    printf("&aa[0][0] = %p\n",&aa[0][0]);
    printf("aa = %p\n",aa);
    printf("&aa = %p\n",&aa);
​
    printf("&aa[0][0] + 1 = %p\n",&aa[0][0] + 1);//四个字节
    printf("aa + 1= %p\n",aa + 1);//八个字节-->二维数组中首个一维数组的地址
    printf("&aa + 1 = %p\n",&aa + 1);//为什么是10?
​
    for(int i = 0;i < 2;i++)
    {
        for(int j = 0;j < 2;j++)
        {
            //scanf("%d",&aa[i][j]);
            scanf("%d",(*(aa+i)+j));
        }
    }
    /**
     * *(*(aa+i)+j)
     * aa:二维数组中首个一维数组的地址;
     * aa + i:二维数组中第i+1个一维数组的地址;
     * *(aa+i):二维数组中第i+1个一维数组的首个元素的地址;
     * *(aa+i)+j;二维数组中第i+1个一维数组的j+1个元素的地址;
     * *(*(aa+i)+j):************的值;
     */
​
    for(int i = 0;i < 2;i++)
    {
        for(int j = 0;j < 2;j++)
        {
            // printf("aa[%d][%d] = %d\n",i,j,aa[i][j]);
            printf("aa[%d][%d] = %d\n",i,j,*(*(aa+i)+j));
        }
    }
​
    return 0;
}

三、再谈数组名的作用

#include <stdio.h>
​
int main(int argc, char const *argv[])
{
    char str[100];//"hello1"
    char ktr[2][100];//"hello2""hello3"
    char ptr[3][2][100];//"hello4""hello5""hello6""hello7"..
​
    printf("Please input str:\n");
    scanf("%s",str);//首元素的地址
​
    printf("str = %s\n",str);
​
    printf("Please input ktr:\n");
​
    for(int i = 0; i < 2;i++)
    {
        //方法一
        //scanf("%s",*(ktr + i));
        //方法二
        scanf("%s",ktr[i]);//*(ktr + i)
    }
​
    for(int i = 0; i < 2;i++)
    {
        //方法一
        printf("ktr[%d] = %s\n",i,*(ktr + i));//ktr[i]
    }
​
    printf("Please input ptr:\n");
​
    for(int i = 0;i < 3;i++)
    {
        for(int j = 0;j < 2;j++)
        {
            scanf("%s",*(*(ptr + i)+j));
            //scanf("%s",ptr[i][j]);
        }
    }
​
    for(int i = 0;i < 3;i++)
    {
        for(int j = 0;j < 2;j++)
        {
            printf("ptr[%d][%d] = %s\n",i,j,*(*(ptr + i)+j));//ptr[i][j]
        }
    }
    return 0;
}

四、数组指针变量的应用场景

数组指针变量:保存数组的地址
如何定义一个数组指针变量 ? 右左法则
    int(*pa)[2];
数组指针的使用场景-->函数传参:定义函数
#include <stdio.h>
​
void print(char* str)
{
    printf("str = %s\n",str);
}
​
void print2(char (*ktr)[100])
{
    for(int i = 0; i < 2;i++)
    {
        //方法一
        printf("ktr[%d] = %s\n",i,*(ktr + i));//ktr[i]
    }
}
​
void print3(char (*ptr)[2][100])
{
    for(int i = 0;i < 3;i++)
    {
        for(int j = 0;j < 2;j++)
        {
            printf("ptr[%d][%d] = %s\n",i,j,*(*(ptr + i)+j));//ptr[i][j]
        }
    }
}
​
int main(int argc, char const *argv[])
{
    char str[100];//"hello1"
    char ktr[2][100];//"hello2""hello3"
    char ptr[3][2][100];//"hello4""hello5""hello6""hello7"..
​
    printf("Please input str:\n");
    scanf("%s",str);//首元素的地址
​
    print(str);
​
    //printf("str = %s\n",str);
​
    printf("Please input ktr:\n");
​
    for(int i = 0; i < 2;i++)
    {
        //方法一
        //scanf("%s",*(ktr + i));
        //方法二
        scanf("%s",ktr[i]);//*(ktr + i)
    }
​
    print2(ktr);
​
    // for(int i = 0; i < 2;i++)
    // {
    //     //方法一
    //     printf("ktr[%d] = %s\n",i,*(ktr + i));//ktr[i]
    // }
​
    printf("Please input ptr:\n");
​
    for(int i = 0;i < 3;i++)
    {
        for(int j = 0;j < 2;j++)
        {
            scanf("%s",*(*(ptr + i)+j));
            //scanf("%s",ptr[i][j]);
        }
    }
​
    print3(ptr);
​
    // for(int i = 0;i < 3;i++)
    // {
    //     for(int j = 0;j < 2;j++)
    //     {
    //         printf("ptr[%d][%d] = %s\n",i,j,*(*(ptr + i)+j));//ptr[i][j]
    //     }
    // }
    return 0;
}

五、指针数组

数组里面保存的都是指针
#include <stdio.h>
#include <stdlib.h>
​
void print4(char **pc)
{
    for(int i = 0; i < 3; i++)
    {
        printf("pc[%d] = %s\n",i,*(pc+i));
​
        //错误//函数参数改成**后正确
        printf("pc[%d] = %s\n",i,pc[i]);//这里代表的是字符,不是字符串\地址
    }
}
​
int main(int argc, char const *argv[])
{
    int * pi[3] = {0};//int (*pi)[3]这个是数组指针,前面是指针数组
​
    printf("sizeof(pi) = %ld\n",sizeof(pi));
​
    //使用
    #if 0
    int num1 = 5;
    int num2 = 6;
    int num3 = 7;
​
    pi[0] = &num1;
    pi[1] = &num2;
    pi[2] = &num3;
​
    for(int i = 0;i < 3;i++)
    {
        printf("pi[%d] = %d\n",i,*pi[i]);
    }
    #endif
​
    #if 0
    //使用注意事项
    //1\局部指针数组里元素都是野指针;需要分配地址
    //2\用完之后释放空间,并置空
    for(int i = 0;i < 3;i++)
    {
        pi[i] = (int *)malloc(sizeof(int));//为每一个地址开辟空间
        scanf("%d",pi[i]);//直接使用,产生段错误
    }
​
    for(int i = 0;i < 3;i++)
    {
        printf("pi[%d] = %d\n",i,*pi[i]);
        free(pi[i]);
        pi[i] = NULL;
    }
    #endif
    //存储的是字符串的首地址,初始化赋值后,不可以改变内容
    char *pc[3] = {"hello1","hello2","hello3"};
​
    print4(pc);
    
    //为每个字符串开辟了空间,每个空间有100个字节,可以之后修改内容
    char ktr[3][100] = {"hello1","hello2","hello3"};
​
    // pc[0] = (char *)malloc(sizeof(char) * 50);
    // pc[1] = (char *)malloc(sizeof(char) * 100);
    
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值