C语言 初识数组

1.数组的定义不可使用变量(支持C99之后的编译可以),但使用可以用变量

#include<stdio.h>
int main()
{
    int n;
    scanf("%d",&n);
    int a[n];               //大部分编译器不支持,不如vs2019    
    

    for(int i=0;i<n;i++)
       a[i]=i;              //[]是一个引用下标操作符


    return 0;
}

2.数组的创建==数组的创建+初始化(建议初始化,防止不可控的变化,养成良好的代码风格)

3.初始化引申的问题,strlen和sizeof的区别

#include<stdio.h>
int main()
{
    char arr1[]={'a','b','c'};  //arr1只有三个元素 ,arr2有4个,多了一个'\0',字符串末尾自动加            
                               //入'\0'
    char arr2[]={"abc"};
    printf("%d",strlen(arr1));  //大于等于3
    printf("%d",strlen(arr2));  //一定是三个


    printf("%d",sizeof(arr1));  //3个
    printf("%d",sizeof(arr2));  //4个




    return 0;
}

strlen是库函数,是读取到'\0'停止,并不读入'\0',数组arr1中没有'\0',因此strlen函数会一直往后读取直到遇到'\0'(数组是在内存中开辟的一块连续空间,数组到头后 后面并非没有数据 ,只是那些数据未赋值使用,因此是随机值)

sizeof是读取多少个字节,包括'\0',因为是char类型,每个元素一个字节,一共4个。

ps:sizeof也是一个操作符,[ ]也是一个操作符。

4.前面说到数组在内存中是连续的,除此之外 地址是从低到高

---------------------------------------------------------------------------------------------------------------------------------

5.二维数组(一般用到二维数组就行了,更高维的比较少见),二维数组可以当成是多个一维数组,如a[3][2]可以看成是3个长度为2的一维数组,其中三个长度为2的一维数组首元素地址就是

a[0][0] a[1][0] a[2][0];

因此二维数组的输入字符串时可以这样写

#include<stdio.h>
int main()
{    
    int a[3][20];
    for(int i=0;i<3;i++)
        scanf("%s",&a[i]); //输入字符串给a[0]就是找到a[0]的位置开始一个个输入字符
                           


    return 0;
}

6.数组的传参,   接下来看两种形式的传参

#include<stdio.h>
void H(int arr1[])==void H(int *arr)  //数组更指针是挂钩的,但是左边的形式更简单,让没上手
int main()                            //指针的初学者使用,简单易懂传数组,用数组接受
{                        

                                      //arr1中可以不标明长度,这取决与你传过去的数组的长度,
                                //这样不会吧代码写死,如果更改下面传的数组长度,函数也要改

    int arr1[5]={0};  //上面传的是数组名【注意传递过程只会传递首元素的地址】
    H(arr1);
    return 0;
}


#include<stdio.h>
void H(int x)
int main()
{                           //这传递的是数组的元素,是一个确定的值(初始化了)
    int arr1[5]={0};
    H(arr1[0]);
    return 0;
}

上面提到传递数组名的过程  就是传递数组首元素的地址,这带来两个问题引入思考

 1.数组名传参是传首元素的地址,这会有什么问题,接下来看代码

 2.数组名有时代表全部元素有时代表首元素,那么到底怎么区分 

问题1:

#include<stdio.h>
void H(int arr[])
{
    sz=sizeof(arr)/sizeof(arr[0]);//这里想求出arr到底有多少个元素,一个int代表4字节,先    
                                 //sizeof
}                               //求出整个数组的占用的字节,再除以一个元素占用的就可以得出长度
int main()                    //很多关于数组的函数问题都会设计数组长度问题,
{
    int arr[]={1,2,4,5,6,4,2,1,3,5};
    H(arr);

    return 0;             //但是这样操作真的能得出数组长度吗?,答案是不能
                         //sz等于1 ,这就是因为传参只传了首元素的地址,所以sizeof(arr)其实
                        //就是sizeof(arr[0]),这样除数被除数都一样答案自然就是1。
}  


//那么正确求长度怎么做呢,一般都是在调用函数前求,然后一起传过去

#include<stdio.h>
void H(int arr[],int sz)
{
    代码块
}                            
int main()                    
    int arr[]={1,2,4,5,6,4,2,1,3,5};
    sz=sizeof(arr)/sizeof(arr[0]);          //求长度
    H(arr,sz);                             //传递过去

    return 0;             
}

 问题2:数组名代表首元素地址(除了两个例外)

1.sizeof+(单独存放的数组名)   //前面提到函数中使用sizeof(arr)代表arr[0]仅仅是因为你传递的只有首元素,那个arr就代表了首元素地址,所以等同于arr[0]。

后面的sizeof(arr)代表的就是整个arr数组占用的字节

2.   &+数组名

&数组名取得是整个数组的地址 ,接下来看代码

#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,9,8 };
	printf("%p\n", arr1);//arr1这里代表首元素地址
	printf("%p\n", &arr1);//&arr1代表整个数组的地址
	printf("%p\n", &arr1[0]);//&arr[0]代表下标为0的元素的地址
	return 0;

}

 可以看到这三个居然一样!更前面说的不一样,但是

&arr取得是整个数组的地址,这个地址也是从首元素出发的,接下来再看一个区别

#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,9,8 };
	printf("%p\n", arr1);//arr1这里代表首元素地址
	printf("%p\n", &arr1);//&arr1代表整个数组的地址
	printf("%p\n", &arr1[0]);//&arr[0]代表下标为0的元素的地址
	printf("\n");
	printf("\n");
	printf("%p\n", arr1 + 1);//arr1这里代表首元素地址
	printf("%p\n", &arr1 + 1);//&arr1代表整个数组的地址
	printf("%p\n", &arr1[0] + 1);//&arr[0]代表下标为0的元素的地址
	return 0;

}

 可以看到第二个地址不一样了

首先+1代表什么,这里+1是指元素+1了,代表跳过一个元素,这里int类型,一个元素4字节,因此+1应该是跳过4,    1和3的结果都是跳过了4,但是2的结果不是。b4+16等于cc(16进制),4+24=28,28进位减16剩12,12是16进制的B,    b进位+1=c。

因此这个&arr+1他跳过的不是一个元素的地址,而是整个数组的地址

从结果可能看不出&arr &arr[0]和arr的区别,但是他们确实有区别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值