数组
常用的数组就是一维数组和二维数组。
一维数组
初始化
char str1[8] = {0};//数组每个元素都是char型,占一个字节
short str1[8] = {0};//数组每个元素都是short型,占两个字节
int str2[8] = {0};//数组每个元素都是int型,占四个字节
char str4[8] = {0}; //完全初始化。数组每个元素都是0
char str5[8] = {1,2,3}; //部分初始化,数组前三个元素是1,2,3,其他为0
char str6[] = {1,2,3,4,5,6}; //由元素来确定数组大小
数组传参
#include <stdio.h>
void fun(char buff1[],char buff2[],char size);
void main(void)
{
char i,str1[]={1,2,3,4,5,6,7,8};
char str2[8]={0};
fun(str1,str2,8);
fun(&str1[0],&str2[0],8);
for(i=0;i<8;i++)
printf("str2[%d]=%d\r\n",i,str2[i]);
}
void fun(char buff1[],char buff2[],char size)
void fun(char *buff1,char *buff2,char size)
{
char i=0;
for(i=0;i<size;i++)
{
buff2[i] = buff1[i]+1;
}
}
fun(str1,str2,8);
fun(&str1[0],&str2[0],8);
这两个传参方式是一样的,因为srt 和 &str[0] 都是表示数组首元素的地址。数组名str 其实是表示 数组首地址,不过数组首地址和数组首元素地址是同一个。
void fun(char buff1[],char buff2[],char size)
void fun(char *buff1,char *buff2,char size)
这两个函数是一样的,都能接收数组地址进行操作。
二维数组
初始化
//2行3列
char str1[2][3] ={0}; //数组每个元素都是char型,占一个字节
short str2[2][3] ={0}; //数组每个元素都是short型,占两个字节
int str3[2][3] ={0}; //数组每个元素都是int型,占四个字节
int str4[2][3] = { {1, 2, 3}, {4, 5, 6} }; //完全初始化,每个元素都复值
int str5[2][3] = {0}; //所有元素都初始化为0
int str6[2][3] = {1}; //只有数组第一个值为1(arr1[0][0]为1),其他所有元素都初始化为0
int str7[][3] = {1,2,3,4,5,6};//确定列,然后行由元素决定
int str7[][3] = {1,2,3,4,5,6}; //正确写法,确定列了可以由元素确定行
int str7[2][] = {1,2,3,4,5,6}; //错误写法,不可以确定行由元素确定列
int str7[][3] = {1,2,3,4,5,6,7}; //正确写法,不足整行的元素会自动补0
数组传参
#include <stdio.h>
void fun(char buff1[2][3],char buff2[2][3],char row,char col);
void main(void)
{
char i,j,str1[][3]={1,2,3,4,5,6};
char str2[2][3]={0};
fun(str1,str2,2,3);
fun(&str1[0],&str2[0],2,3);
fun(&str1[0][0],&str2[0][0],2,3);//错误用法
for(i=0;i<2;i++)
for(j=0;j<3;j++)
printf("str2[%d][%d]=%d\r\n",i,j,str2[i][j]);
}
void fun(char buff1[2][3],char buff2[2][3],char row,char col)
void fun(char buff1[][3],char buff2[][3],char row,char col)
void fun(char (*a)[3],char(*b)[3],char row,char col)
void fun(char **buff1,char **buff2,char row,char col) //错误
{
char i=0,j=0;
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
buff2[i][j] = buff1[i][j]+1;
}
}
fun(str1,str2,2,3);
fun(&str1[0],&str2[0],2,3);
fun(&str1[0][0],&str2[0][0],2,3);//错误用法
前两种传参方式是一样的,第一种是二维数组首地址,第二种是第0行首元素地址,是同一个地址。第三种是第0行第0列元素地址,也是同一个地址,而且执行效果是一样的,但是有警告,语法有问题,不建议使用。
void fun(char buff1[2][3],char buff2[2][3],char row,char col)
void fun(char (*a)[3],char(*b)[3],char row,char col)
void fun(char buff1[][3],char buff2[][3],char row,char col)
void fun(char buff1[2][],char buff2[2][],char row,char col) //错误
void fun(char **buff1,char **buff2,char row,char col) //错误
跟初始化时候一样,传参时也只可以确定列不确定行,不可以确定行不确定列。
在使用多维数组时,初始化或者传参时,第一维的数量是可以不写的,其他维度必须写
那为什么不能用二维指针直接指二维数组呢?
因为二级指针是指向一级指针的指针,一级指针是取一次地址,二级指针是取两次地址。根据二维数组是连续存放的特性,取了一次地址之后,所有元素的地址就全部知道了,只需要指针的移动就可以遍历所有的元素了,不需要再取一次地址了。
数组的地址偏移问题
一维数组
#include <stdio.h>
void main(void)
{
int a[10]={0};
printf(" &a=%p\r\n",&a);
printf(" a=%p\r\n",a);
printf(" &a[0]=%p\r\n",&a[0]);
//printf("a[0]=%p\r\n",a[0]);
printf(" &a+1=%p\r\n",&a+1);
printf(" a+1=%p\r\n",a+1);
printf("&a[0]+1=%p\r\n",&a[0]+1);
//printf("a[0]+1=%p\r\n",a[0]+1);
}
从各个地址可以看出,&a、a、&a[0]表示的是同一地址,但是表示的含义不一样。
&a+1地址与&a相比,偏移了40个字节,即声明数组的空间大小。
a+1地址与a相比,偏移了4个字节,即数组中一个元素的空间大小。
&a[0]+1地址与&a[0]相比,偏移了4个字节,即数组中一个元素的空间大小。
&a指向整个数组的地址,偏移也是按照整个数组大小偏移的。
a 数组名表示的是数组首元素地址,按照一个元素大小偏移。
&a[0]表示数组首元素地址。按照一个元素大小偏移。
二维数组
#include <stdio.h>
void main(void)
{
int a[2][3]={0};
printf(" &a=%p\r\n",&a);
printf(" a=%p\r\n",a);
printf(" &a[0]=%p\r\n",&a[0]);
printf("a[0]=%p\r\n",a[0]);
printf("&a[0][0]=%p\r\n",&a[0][0]);
// printf("a[0][0]=%p\r\n",a[0][0]);
printf(" &a+1=%p\r\n",&a+1);
printf(" a+1=%p\r\n",a+1);
printf("&a[0]+1=%p\r\n",&a[0]+1);
printf("a[0]+1=%p\r\n",a[0]+1);
printf("&a[0][0]+1=%p\r\n",&a[0][0]+1);
//printf("a[0][0]+1=%p\r\n",a[0][0]+1);
}
&a、a、&a[0]、a[0]、&a[0][0]表示的是同一地址,但是表示的含义不同。
&a+1地址与&a相比,偏移了24个字节,即声明数组的空间大小。
a+1地址与a相比,偏移了12个字节,即数组中一行元素的空间大小。
&a[0]+1地址与&a[0]相比,偏移了12个字节,即数组中一行元素的空间大小。
a[0]+1地址与a[0]相比,偏移了4个字节,即数组中一个元素的空间大小。
&a[0][0]+1地址与&a[0][0]相比,偏移了4个字节,即数组中一个元素的空间大小。
&a 指向整个数组的地址,偏移也是按照整个数组大小偏移的。
a 数组名表示的是数组首行地址,按照一行大小偏移。
&a[0] 表示数组首行地址。按照一行大小偏移。
a[0] 表示的是首行首元素的地址,按照一个元素大小偏移。
a[0][0] 表示的是首行首列的元素地址,按照一个元素大小偏移。