在数组运算前,先了解一下数组的解引用到底是怎么回事。
#include <windows.h>
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,0};
printf("%d\n", *arr);
system("pause");
return 0;
}
由此可见,数组的数组名其实是数组首元素的地址。
那么,如果要访问一个数组中其他元素呢?
#include <stdio.h>
int main()
{
int arr[10] = {0};
int i = 0;
for(i=0; i<sizeof(arr)/sizeof(arr[0]); ++i)
{
printf("&arr[%d] = %p\n", i, &arr[i]);
printf("%p\n", arr+i);
}
return 0;
}
这里输出的是&arr[i]的地址,那么从arr[0]到arr[9]的地址能不能通过arr+i的方式打印出来呢?我们来看
观察结果我们发现,通过对数组名+整数的运算,其实可以获取到数组每个人元素的地址。这样我们就可以用指针访问我们的数组了。
看完一维数组的表示方式,下列关于数组的一些运算我们必须掌握。
//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a)); //16 数组的大小(4个元素,一个占4个字节)
printf("%d\n",sizeof(a+0)); //4 第一个元素的大小
printf("%d\n",sizeof(*a)); //4 数组的解引用,数组首元素的大小(int型)
printf("%d\n",sizeof(a+1)); //4 第二个元素的大小
printf("%d\n",sizeof(a[1])); //4 第二个元素的大小
printf("%d\n",sizeof(&a)); //4 数组的地址大小都是4
printf("%d\n",sizeof(&a+1)); //4 这个数组的下一个数组的地址
printf("%d\n",sizeof(&a[0])); //4 首元素的地址
printf("%d\n",sizeof(&a[0]+1)); //4 第二个元素的地址
//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr)); //6 数组的大小(6个元素,一个占1个字节)
printf("%d\n", sizeof(arr+0));//4 首元素的地址
printf("%d\n", sizeof(*arr)); //1 数组的解引用,首元素的大(char型)
printf("%d\n", sizeof(arr[1]));//1 第二个元素的大小
printf("%d\n", sizeof(&arr)); //4 数组的地址是4
printf("%d\n", sizeof(&arr+1));//4 下个数组的首地址
printf("%d\n", sizeof(&arr[0]+1));//4 第二个元素的地址
printf("%d\n", strlen(arr)); //随机
printf("%d\n", strlen(arr+0));//随机
/*
printf("%d\n", strlen(*arr));//error
*/
/*printf("%d\n", strlen(arr[1]));*/ //error
printf("%d\n", strlen(&arr));//随机
printf("%d\n", strlen(&arr+1));//随机
printf("%d\n", strlen(&arr[0]+1));//随机
为什么在运算strlen 时会出现这么多随机数呢?不妨先来看看strlen的用法
它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止
而对于strlen(*arr),在对arr解引用求长度时,会自动将首元素的地址先用ASCII码值表示出了,然后向后查找,系统会一直查找下去(a的ASCII为97)
strlen(&arr)是对arr的地址求长度,而arr的地址里没'\n',所以他会一直找到'\n'才能停下了,会产生一个随机值
char *p = "abcdef";
printf("%d\n", sizeof(p)); //4 首元素的地址
printf("%d\n", sizeof(p+1));//4 第二个元素的地址
printf("%d\n", sizeof(*p));//1 首元素的大小
printf("%d\n", sizeof(p[0]));//1 首元素的大小
printf("%d\n", sizeof(&p));//4 指针的地址为4
printf("%d\n", sizeof(&p+1));//4 下个指针的地址
printf("%d\n", sizeof(&p[0]+1));//4 第二个元素的地址
printf("%d\n", strlen(p));//6 求整个数组的长度
printf("%d\n", strlen(p+1));//5 从第二个元素开始的长度
/**printf("%d\n", strlen(*p));//error
printf("%d\n", strlen(p[0]));*///error
printf("%d\n", strlen(&p));//x 从首元素地址开始找'\n',随机值
printf("%d\n", strlen(&p+1));//x 同上
printf("%d\n", strlen(&p[0]+1));//5第二个元素开始的长度
这里产生的错误和上面的strlen 一样会从首元素对应的ASCII值出查找,所以一样会出错。
//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//48 整个数组的大小
printf("%d\n",sizeof(a[0][0]));// 4 第一个元素的大小
printf("%d\n",sizeof(a[0]));//16 第一行元素的大小(int型)
printf("%d\n",sizeof(a[0]+1));//4 第一行的第二个元素的大小
printf("%d\n",sizeof(a+1));//4 第二个元素的地址
printf("%d\n",sizeof(&a[0]+1));//4 第一行第二个元素的地址
printf("%d\n",sizeof(*a));//16 数组首元素(相当于第一行的大小)
printf("%d\n",sizeof(a[3]));//16 下个数组的首个元素(第一行)大小
接下来总结一下sizeof和strlen的区别:
sizeof:
1、sizeof的单位是字节
2、sizeof(数组名)表示整个数组的大小(和类型有关)
3、sizeof(&数组名)表示整个数组的地址(和类型无关)
4、sizeof(*数组名)表示数组首元素的大小
strlen:
1、strlen(数组名)表示数组的长度(如果是非字符串则会产生一个随机值)
2、strlen(*数组名)表示从首元素对应的ASCII开始找'\n',会出错
3、strlen(&数组名)表示从首元素的地址开始找'\n',直到找到'\n',会产生一个随机值
结果和你想的一样吗?