一.初始化
1.整体初始化
①数组未初始化,数组里面的值都是随机值。
int arr[12];
for(int i=0;i<12;++i){
printf("%d ",arr[i]);
}
②数组初始化为{0}
,数组里面的值都是0
。
int arr[12] = {0};
for(int i=0;i<12;++i){
printf("%d ",arr[i]);
}
③数组初始化为非零值,数组里面第一个值是非零值,其他的值都是0
。
int arr[12] = {2};
for(int i=0;i<12;++i){
printf("%d ",arr[i]);
}
2.部分初始化
指定下标的值被赋值,其他的值都是0
。这是C99语法。
int arr[12] = {[2]=2,[5]=5};
for(int i=0;i<12;++i){
printf("%d ",arr[i]);
}
3.不同数组类型的大小
char carr[12];
int iarr[12];
double farr[12];
printf("carr = %d\n",sizeof(carr));
printf("iarr = %d\n",sizeof(iarr));
printf("farr = %d\n",sizeof(farr));
输出:
carr = 12 // 1 x 12
iarr = 48 // 4 x 12
farr = 96 // 8 x 12
4.数组不能改名
#include<stdio.h>
int main(){
int arr[] = {1,2,3,4,5,6,7,8};
int p = arr;
for(int i=0;i<8;++i){
printf("%d\n",p[i]);
}
}
是无法运行的
二.数组与指针
1.数组的地址
数组名是数组第一个元素的地址。
int arr[] = {1,2,3,4,5,6,7,8};
printf("&arr=%p\n",&arr);
printf("arr=%p\n",arr);
printf("&arr[0]=%p\n",&arr[0]);
输出:
&arr=000000000062FE00
arr=000000000062FE00
&arr[0]=000000000062FE00
也可以用指针实现数组
操作 | 下标 | 指针 | |
1 | 第i 个元素值 | arr[i] | *(arr+i) |
2 | 第i 个元素地址 | &arr[i] | arr+i |
例如:
int arr[] = {1,2,3,4,5,6,7,8};
for(int i=0;i<8;++i){
printf("%d\n",*(arr+i));
} //在C语言中只能逐个地使用下标变量
2.数组名放入指针
地址存储在指针中。可以用指针操作地址。
int arr[] = {1,2,3,4,5,6,7,8};
int* p = arr;
for(int i=0;i<8;++i){
printf("%d\n",*(p+i));
}
三.函数与数组
1.数组用作参数函数有两种形式,一种是数组元素作为函数调用的实参使用;另一种是数组名作为函数调用的形参和实参使用。
①数组元素作为函数的参数
与普通变量是完全相同的。
例:给一段数字判断哪个最大
float max(float x,float y){
if(x>y) return x;
else return y;
}
int main(){
float m,a[10] = {12.3,105,34.5,50,67,9,78,98,89,-20};
int k;
m = a[0];
for(k=1;k<10;k++){
m = max(m,a[k]);
}
printf("%.2f\n",m);
}
②数组名作为函数的参数
数组名作为函数参数时,通常必须再用一个参数传入数组大小。例:
#include <stdio.h>
void PrintArr1(int arr[],int n){
for(int i=0;i<n;++i){
printf("%d ",arr[i]);
}
printf("\n");
}
void PrintArr2(int* arr,int n){
for(int i=0;i<n;++i){
printf("%d ",arr[i]);
}
printf("\n");
}
int main(){
int array[] = {1,2,3,4,5,6,7,8,9};
PrintArr1(array,9);
PrintArr1(array,3);
PrintArr1(array+6,3);//从下标为6的数组开始输入
PrintArr1(array+3,3);//从下标为3的数组开始输入
}
其中,array为实参,arr为形参,实际上形参数组并不存在,系统把实参数组的首地址赋给形参数组名,形参数组和实参数组共享一段内存空间;因此当形参变化时,形参和实参共享的数组就发生了变化,即实参随之变化。
输出:
1 2 3 4 5 6 7 8 9
1 2 3
7 8 9
4 5 6
数组作为参数时,数组退化成指针,不能利用sizeof
获取数组大小,也就不能计算数组元素个数。
2.数组作为函数参数和返回值时,传指针/地址
四.多维数组
1.语法
类型 二维数组名[行数][列数];
2.初始化
int days[4][3]={
{31,28,31},
{30,31,30},
{31,31,30},
{31,30,31}
};
简化:
①省略内部括号
int days[4][3]={31,28,31,30,31,30,31,31,30,31,30,31};
②省略行标(第一维大小)
int days[][3]={31,28,31,30,31,30,31,31,30,31,30,31};
3.二维数组输入
int n,m;
scanf("%d%d",&n,&m);
int arr[n][m];
for (int i=0;i<n;++i){
for (int j=0;j<m;++j){
scanf("%d",&arr[i][j]);
}
}
4.多维数组的地址
例:
int a[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}}
将a数组的三行看成三个分数组:a[0],a[1],a[2]。每个分数组是含5个列元素的一维数组。
a,a+1和a+2分别是指向0号分数组,1号分数组和2号分数组的指针常量
(对应的地址字节为65470,65480,65490,基本类型字节数是10)
a[0],a[1],a[2]分别是指向各数组0号元素a[0][0],a[1][0],a[2][0]的指针常量
(对应的地址字节还为65470,65480,65490,但基本类型字节数是2)
a[0]+1和a[0]+2是分别指向a[0][1]和a[0][2]的指针常量
(对应的地址字节为65472,65474)
数组元素中“[ ]”是变址运算符,相当于*( + )
- a[i][j] --> *(a[i]+j) --> *(*(a+i)+j)
五.const数组
数组变量已经是const
指针,表示数组中的每一个元素都是const int
,即每个元素不能通过arr
改变。
例:
const int arr[]={1,2,3,4,5,};
arr[0] = 0;
会出现错误
六.数组指针
#include <stdio.h>
int main () {
int n = 10;
int *p;
p = &n; // p指针指向变量
printf("*p = %d\n",*p);
int arr[] = {1,2,3,4,5,};
p = arr;// p指针指向数组
printf("*p = %d\n",*p);
printf("*(p+1) = %d\n",*(p+1));
printf("*(p+2) = %d\n",*(p+2));
printf("*(p+3) = %d\n",*(p+3));
printf("*(p+4) = %d\n",*(p+4));
return 0;
}