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的区别,但是他们确实有区别