1、在正式介绍知识点之前,我们应该明确一些基本知识。
(1)一般情况下数组名都是代表首元素的地址,除了以下两种情况:
<1>sizeof(数组名) //注意:()里仅有数组名,不能有其它的东西
<2>&数组名
(2)sizeof()函数的作用
sizeof()计算的是对象所占内存的大小,单位为字节
(3)strlen()函数的功能
strlen()计算从起始地址开始往后数,直到遇到'\0'才停止,并返回从开始到'\0'之间有多少个元素,不包括'\0'。
(4)指针变量和地址(指针)占的内存大小
指针变量和地址在32位环节下占4个字节,在64位环境下占八个字节
(5)各类型数据所占字节数
char unsigned char 1个字节
short unsigned short 2个字节
int unsigned int long float 4个字节
double long double 8个字节
接下来再继续看正式内容。
2、一维整形数组
首先定义一个整形数组:int a[ ]={1,2,3,4};
我们来分析一下这些符号代表什么以及语句输出什么:
(1)a //单独存在的一维数组名为首元素地址
sizeof(a) //sizeof(数组名),这时a表示整个整形数组的地址,计算的是整个数组所占内存的字节数
printf(“%d\n”,sizeof(a)); //打印的是整个数组所占字节数,则为4*4=16个字节
(2)a+i //整形数组中第i个元素的地址,i=0时,就是a,也就是首元素的地址
printf(“%d\n”,sizeof(a+i)); //打印的是第i个元素地址所占字节数,则为4 / 8(32位环境下4个字节,64位环境下8个字节),即使i=0,表达式变成printf(“%d\n”,sizeof(a+0));也只是打印首元素地址所占字节数,而非整个数组地址所占字节数
(3) *(a+i)== a[i] //代表的是第i个元素所占字节数
printf(“%d\n”,sizeof(*(a+i))); // 就相当于写成printf(“%d\n”,sizeof(a[i]));打印数组第i个元素所占字节数。
(4)&a //代表的是整个数组的地址,它的值==&a[0]==a,但是它的类型不一样,int *p[4]=&a;
printf(“%d\n”,sizeof(&a)); //计算的是整个数组的地址所占字节数,数组的地址也是地址,则值为4/8
printf(“%d\n”,sizeof(&a+1)); //&a为整个整形数组的地址,那么+1跳过的就是整个数组的地址,指向a数组最后一个元素后面一个元素,那么&a+1还是地址,则输出为4/8个字节,那如果变成 printf(“%d\n”,sizeof(&a+i));那也是打印一个地址所占字节数,那么还是4/8个字节
(6)&a[i] //代表的是数组中第i个元素的地址所占的字节数
&a[0]+i //代表的也是数组中第i个元素的地址所占字节数
printf(“%d\n”,sizeof(&a[i])); //输出为4/8字节
printf(“%d\n”,sizeof(&a[0]+i )); //输出为4/8字节
(7)*&a //根据操作符的先后性,先进行&运算,再*运算:先取出整个数组的地址,然后再解引用。有两种理解方式:第一种 *&a得到的是整个数组的所有元素,然后计算整个数组所有元素所占的总字节数,为4*4个字节;第二种 *和&抵消,只剩下 a这个数组名,然后sizeof(a),此时a又代表整个数组的地址,计算的还是整个数组所占的字节数。
3、一维字符型数组
<1> 定义一个字符型数组 char arr[]={ 'a', 'b', 'c' ,'d' , 'e', 'f' };
(1)arr //首元素地址
printf(“%d\n”,sizeof(arr)); //计算的是整个数组的所占字节数,值为6*1=6个字节
printf(“%d\n”,strlen(arr)); //arr的值为首元素的地址==&a[0],则strlen从a[0]的地址开始,往后读,直到遇到'\0'为止,而arr数组中没有'\0',因此不知道何时停止,则这个表达式为一个随机值。
(2)arr+i //等于&arr[i],代表数组中第i个元素的地址,占4/8个字节
&arr[0]+i //数组第i个元素的地址,其本身性质为地址,那么占4/8个字节
printf(“%d\n”,sizeof(arr+i)); //输出的是数组中第i个元素的地址,值为4/8个字节
printf(“%d\n”,strlen(arr+i)); //strlen从a[i]的地址开始,往后读,直到遇到'\0'为止,而arr数组中没有'\0',因此不知道何时停止,则这个表达式为一个随机值。
(3)*arr //代表数组首元素所占内存的字节数,每个元素的类型都是char型,只占一个字节
*arr+i //代表数组第i个元素所占内存的字节数,都只占一个字节
arr[i] //同上
printf(“%d\n”,strlen(*arr+i)); //把arr[i]的值传给strlen函数,这个是非法的。比如arr[0]的为‘a’的大小,也就是97,97这个地址是不能被用户访问的,非法访问,会报警告。
(4)&arr //整个数组的地址,值==&a[0]==a,其本身性质为地址,那么占4/8个字节
&arr+1 //数组最后一个元素的后面一个地址,其本身性质为地址,那么占4/8个字节
printf(“%d\n”,strlen(&arr+i)); //这个表达式为一个随机值
<2> 定义一个字符型数组 char arr[]="abcdef";
接下来我就只列举出与上一个数组不同的地方:
(1)sizeof(arr) //值为7,因为字符串“abcdef”的内容为 'a', 'b', 'c' ,'d' , 'e', 'f'以及'\0',共七个char型元素,占7*1==7个字节;
(2)strlen(arr) //遇到'\0'就停止,从&arr[0]处开始到'\0'就结束,共有六个元素
strlen(&arr[0])== strlen(arr)//共有六个元素
strlen(arr+1)//从&arr[1]处开始到'\0'就结束,共有五个元素
(3)strlen(&arr)//随机值
strlen(&arr+1)//随机值
(4)strlen(*arr[i])//err,与上一个数组理由一样
4、二维数组(有难度)
先定义一个二维整形数组 :int a[3][4]={0};
我先来介绍一下二维数组的一些小知识:
二维数组在内存中其实是连续存放的,并不是一行一行的存放的,我们之所以把它分成多行是为了方便观察。
(1)a //代表数组首元素的地址,又因为是二维数组,因此代表二维数组第一行的地址。
sizeof(a)//a单独存放的时候,代表二维数组第一行的地址,但是单独在sizeof()里面时就代表整个二维数组的地址了,计算的是整个二维数组元素所占内存空间的大小,总共有3*4==12个元素,每个元素都是int型,故占内存大小为12*4==48个字节。
(2)a+i;//代表第i行的地址
sizeof(a+i);//计算的第i行的地址,第i行的地址本身也是地址,其值为4/8
*(a+i)// == a[ i ] 第 i 行数组名,代表第 i 行第一个元素的地址
sizeof(*a)//数组名单独放在sizeof()中,计算的第一行所有元素所占内存的字节数,值为16
sizeof(*(a+i))//计算第i行所有元素所占内存的字节数,值为16
(3)a[i] //在二维数组中,a[i]代表的第i行第一个元素的地址,但同时也是第i行的数组名
sizeof(a[i])//计算第一行元素所占内存空间的字节数,值为4*4==16。在二维数组开头那张手绘图片中有写到,其实每一行都是一个一维数组,而a[i]其本身就是该行一维数组的数组名,数组名单独存放在sizeof()里面,则代表整个数组所占内存的大小,也就是代表第i行这个一维数组所有元素所占内存的字节数。(一定要记住!!!这个很容易弄混淆)
sizeof(a[0]+1)//计算的是第一行第二个元素的地址也就是&a[0][1]所占内存的字节数,值为4/8。刚才有提到 a[0]其实是第一行一维数组的数组名,由于单独放在sizeof()里边故被当成第一行整个数组的地址。而此时,a[0]并没有单独放在sizeof()里边,a[0]因此代表的是第一行一维数组首元素的地址也就是第一行第一个元素的地址,a[0]+1则代表第一行第二个元素的地址,值为4/8。
(4)&a[i] //a[i]代表第i行的数组名,也是第i行的地址,&数组名,则取出了整个数组的地址
&a[0]+i //同上
sizeof(&a[i])//&a[i]为第i行整个一维数组的地址,但不是数组名,其本质为一个地址,值为4/8
sizeof(&a[0]+i)//同上
&a[0]+i与&a[i] 是一模一样的,但与a[i]还是不同。
*a //第一行所有元素
sizeof(*a) //第一行所有元素占内存的字节数,值为4*4==16。
*a+i //第i行的所有元素
sizeof(*a+i)//第i行所有元素占内存的字节数,值为4*4==16。
(5)*(a[i]+j)//代表的是第i行第j列元素,等同于a[i][j]
sizeof(*(a[i]+j)) //计算的是第i行第j列元素所占内存的字节数,值为4。
等同于sizeof(a[i][j]);
a[i][j] //代表第i行第j列个元素
sizeof(a[i][j])//求的是第i行第j列个元素所占内存的字节数,类型为int型,占四个字节
指针这块的知识非常繁琐,必须要多记多想多练,才能熟能生巧。
以上就是我对一维数组的首元素名,数组名,&数组名和二维数组首元素、数组名,&数组名,行数组名的理解。如果有错误的地方,恳请斧正。