以下题目皆是在x64的环境下进行。
一,整形数组
先定义一个整形数组:
求下列各题打印结果:
①
一般情况下,数组名代表的是首元素的地址,但是如果是sizeof(数组名)的形式,数组名单独放在sizeof()内,此时数组名代表的是整个数组,所以此时sizeof()所求的是整个数组所占内存的大小,大小为16个字节。
②
这一题数组名并没有单独放在sizeof()里,所以a代表的是首元素的地址,a+0依旧是首元素的地址,而地址在x64的环境下所占的内存都是8个字节(如果在x86的环境下,地址所占内存大小为4个字节)。
③
这一题就相当于是sizeof(*(a+0)),即sizeof(a[0]),所以sizeof()所求的是a[0]所占内存的大小大小,为4个字节。
④
这一题数组名没有单独放在sizeof()里,a代表的是首元素的地址,a+1代表的是数组中第二个元素的地址,既然是地址,那么在x64的环境下所占内存大小就是8个字节。
⑤
这一题显而易见所求的就是数组中a[1]所占内存大小,即4个字节。
⑥
数组名取地址,取的是整个数组的地址,既然是地址,在x64的环境下所占内存就是8个字节。
⑦
先对数组a取地址,取出整个数组的地址,然后再解引用,也就得到了整个数组,所以此时所求的的是整个数组所占内存的大小16个字节。其实也可以理解为*与&可以相互抵消了,所以这题也就相当于是sizeof(a)。
⑧
取数组a的地址,再+1,得到的还是一个地址,所占内存大小也时8个字节。&a + 1跳过了一整个数组,也就是16个字节,此时已经超出了这个数组的范围,但是因为sizeof内部不会进行实际运算,所以不会出现越界。
⑨
取a[0]这个元素的地址,所占内存大小为8个字节。
⑩
取a[0]的地址,再+1,得到的是a[1]的地址,所占内存大小为8个字节。
二,字符数组
先定义一个字符数组:
求下列各题打印结果:
①
这题这之前的题目一样,arr单独放在sizeof()里,所求的是整个数组所占内存的大小,6个字节。
②
arr并没有单独放在sizeof()里,所以arr代表的是首元素的地址,arr+0依旧是首元素的地址,所占内存大小为8个字节。
③
这一题就相当于是sizeof(*(a+0)),即sizeof(a[0]),所以sizeof()所求的是a[0]所占内存的大小大小为1个字节。
④
这题所求的就是数组中元素a[1]所占内存大小,即为1个字节。
⑤
&arr取出的是整个数组的地址,既然是地址,那么所占内存大小就是8个字节。
⑥
&arr取的是整个数组的地址,然后再+1,跳过了整个数组6个字节,指向的还是一个地址,所站内存就是8个字节。
⑦
&arr[0]+1,也就相当于&arr[1],也是一个地址,所占内存大小为8个字节。
⑧
strlrn是用来计算字符串长度的库函数,原理是传入一个地址,从这个地址开始向后遍历,每次跳过一个字节,在遇到\0时停下。我们在定义字符串时,系统会自动在字符串末尾加上\0,但是在字符数组中,则不会自动加上\0,上面我们定义的字符数组并没有\0。当我们把arr也就是首元素地址传给strlen时,strlen会从arr[0]开始向后遍历,遍历到数组最后依旧没有遇到\0,就会继续向后查找,直到遇到\0才停下,由于我们不知道什么时候才知道会遇到\0,所以此时strlen()所求出的长度是一个随机值。设这个随机值为n。
⑨
这题其实和上一题是一样的,也是把arr[0]的的值传给strlen,所以这题所求的出的长度也是一个的随机值。这个随机值也是n,和上一题相同。
⑩
这题我们把*arr传给了strlen(),*arr是也就是arr[0],是一个字符,但是我们知道,strlen()函数要求传给它的参数是一个地址,如果我们把一个字符传给它,那么系统就会报错,提示非法访问。
⑪
这题和上面一道题类似,也是传了一个字符作为参数给strlen(),系统报错,提示非法访问。
⑫
这题我们把整个数组的地址传给了strlen(),虽然是整个数组的地址,但是指向的还是arr[0],是一个数组指针,当传给stelen()后,strlrn的形参形式是const char*,所以系统会把数组指针当成字符指针来处理,所以还是从arr[0]开始向后遍历,每次跳过一个字节,所求长度是一个随机值,并且和第8、第9题结果一样为n。
⑬
&arr取的是整个数组的地址,+1则是跳过了整个数组6个字节,把数组地址作位参数传给strlen(),和上一题是一样的,只不过这题strlen()是从arr[5]的后一个地址开始向后遍历,所求长度是一个随机值,并且结果为n-6。
⑭
&arr[0]+1,其实就是&arr[1],把arr[1]的地址作位参数传给strlen(),从arr[1]开始向后遍历,所求长度是个随机值,并且结果结果为n-1。
三,字符串
先定义一个字符串:
求下列各题打印结果:
①
这题求的是整个字符串所占内存大小,这题我们定义的是字符串,系统在末尾自动添上\0,所以整个字符串所占内存大小为7个字节。
②
arr没有单独放在sizeof()内,所以arr代表首元素的地址,arr+0,还是首元素的地址,所占内存大小为8个字节。
③
这题相当于sizeof(a[0]),求的是a[0]所占内存大小,为1个字节。
④
这题所求就是字符串中元素a[1]所占内存大小,为1个字节。
⑤
&arr取出的是整个字符串的地址,既然是地址,所占内存大小就是8个字节。
⑥
这题就是先取整个字符串的地址,然后再+1,跳过了一个7个字节,指向了arr[6]的后一个地址,所占内存大小为8个字节。
⑦
这一题先取arr[0]的地址,然后再+1,得到的是arr[1]的地址,所占内存大小为8个字节。
⑧
arr代表的是首元素地址,这次我们定义的是字符串,第7个元素是\0,所以求出的长度为6。
⑨
这一题和上题一样,arr+0还是代表首元素的地址,所以求出的长度为6。
⑩
strlen()要求形参类型为字符指针(一个地址),*arr相当于是arr[0],把字符串的一个元素作位参数传给strlen()函数,系统会报错,提示非法访问。
⑪
这一题和上一题一样,把字符串的元素作为参数从传给了strlen()函数,系统报错,提示非法访问。
⑫
这题我们把整个字符串的地址传给了strlen(),虽然是整个字符串的地址,但是指向的还是arr[0],当传给strlen()后,strlrn的形参形式是const char*,所以系统会把数组指针当成字符指针来处理,所以还是从arr[0]开始向后遍历,每次跳过1个字节,当遍历到arr[6]也就是\0时,就停止了,返回求到的字符串长度,长度为6。
⑬
这题就是先取整个字符串的地址,然后再 + 1,跳过了7个字节,指向了arr[6]的后一个地址,把这个地址作为参数传给strlen()函数。和上一题一样,strlen()函数从arr[6]的后一个地址开始向后遍历,知道遇到\0才停止,我们并不知道什么时候才能遇到\0,所以所求长度为随机值。
⑭
这一题是吧&arr[0]+1,也就是&arr[1]作为参数传给strlen(),strlen()从arr[1]开始向后遍历,遇到arr[6]也就是\0时停止,返回字符串长度为5。
四,二维数组
先定义一个二维数组:
关于二维数组,我们要知道,二维数组的数组名指的首元素其实是第一行的数组,例如上面定义的二维数组,它的数组名a代表的首元素是数组a[0]。同时,这个二维数组第一行数组的数组名a[0]代表的首元素是a[0][0]。
求下列各题打印结果:
①
a是二维数组的数组名,单独放在sizeof()内,代表的是整个二维数组,所占内存大小为48个字节。
②
这一题所求的就是二维数组中元素a[0][0]所占内存大小,为4个字节。
③
a[0]是a这个二维数组中第一行的数组的数组名,数组名单独放在sizeof()内,代表的是整个数组,第一行的数组所占内存大小为16个字节。
④
a[0]是第一行数组的数组名,代表的是第一行数组首元素的地址,也就是相当于&a[0][0],而a[0]+1,就相当于&a[0][1],也是一个地址,所占内存大小为8个字节。
⑤
a[0]+1相当于&a[0][1],再解引用,也就是求a[0][1]所占内存大小,为4个字节。
⑥
a是二维数组的数组名,代表的是首元素的地址,二维数组的首元素也就是第一行数组。第一行数组的地址+1,也就是第二行数组的地址,既然是地址,所占内存大小就是8个字节。
⑦
承接上题,a+1是第二行数组的地址,再解引用,就是第二行整个数组,所占内存大小为16个字节。
⑧
&a[0]取的是第一行整个数组的地址,再加1,就是第二行整个数组的地址,所占内存大小为8个字节。
⑨
承接上题,&a[0]+1是第二行整个数组的地址,再解引用,就是第二行整个数组,所占内存大小为16个字节。
⑩
a是二维数组的数组名,代表的是首元素也就是第一行元素的地址,再解引用,也就是第一行的所有元素,所占内存大小为16个字节。
⑪
a[3]是第四行数组的数组名,但是我们定义的二维数组只有三行,按理来说已经越界了。但是因为sizeof内部的表达式不会真正的访问(计算),只要能确定sizeof()内部表达式的类型就可以了,不需要计算,所以这题并不存在越界访问,所以a[3]所占内存大小为16个字节。
总结:
数组名的意义:
- sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
- &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
- 除此之外所有的数组名都表示首元素的地址。
新手上路,请多指教。