关于数组的一些运算
我们先看看运算符sizeof和函数strlen函数的作用定义和用法。
sizeof:sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回对象或者类型所占内存的字节数。
MSDN上的解释为:
The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type(including aggregate types). This keyword returns a value of type size_t.
其返回值类型为size_t,在头文件stddef.h中定义。这是一个依赖于编译系统的值,一般定义为
typedef unsigned int size_t;
sizeof有三种语法形式,如下:
sizeof(object);//sizeof(对象);
sizeof(type_name);//sizeof(类型);
sizeofobject;//sizeof对象;
sizeof 的应用数组的sizeof值等于数组所占用的内存字节数,如:
char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 结果为4,字符 末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3*4=12(依赖于int)
值得一提的是,sizeof(只有数组名),则表示的是数组占用的大小。sizeof(arr+0)则表示第一个元素
占用的大小。不要误以为sizeof是直接计算数组长度的,当计算长度时应该使用:
int c1 = sizeof( a1 ) / sizeof( char ); // 总长度/单个元素的长度
int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 总长度/第一个元素的长度
———————————————————————————————————————————————————
strlen:strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')。其头文件是string.h
———————————————————————————————————————————————————
1.先看看一维数组的运算。
int arr[]={1,2,3,4};
printf("%d\n",sizeof(arr)); //16
printf("%d\n",sizeof(arr+0)); //4
printf("%d\n",sizeof(*arr)); //4
printf("%d\n",sizeof(arr+1)); //4
printf("%d\n",sizeof(arr[1])); //4
printf("%d\n",sizeof(&arr)); //4
printf("%d\n",sizeof(&arr+1)); //4
printf("%d\n",sizeof(&arr[0])); //4
printf("%d\n",sizeof(&arr[0]+1));//4
对上面一维数组进行了简单的运算和预测。
来看看输出的结果如何:
真实结果和预测结果一毛一样。
还有一个sizeof的坑:
void foo3(char a3[3])
{
int c3 = sizeof( a3 ); // c3 ==
}
void foo4(char a4[])
{
int c4 = sizeof( a4 ); // c4 ==
}
这里的c3 答案并不是3,因为此时a3并不是作为数组传进函数,而是指针,
相当于char *a3,我们只是将a3地址传入,所以指针所占为4字节。
——————————————————————————————————————————————————
字符数组:
例:
int main()
{
char arr[]={'a','b','c','d','e','f'};
printf("%d \n",sizeof(arr)); //6 整个数组元素大小。
printf("%d \n",sizeof(arr+0)); //4 首元素地址
printf("%d \n",sizeof(*arr)); //1 第一个元素大小
printf("%d \n",sizeof(arr[1])); //1 第一个元素大小
printf("%d \n",sizeof(&arr)); //4 数组地址
printf("%d \n",sizeof(&arr+1)); //4 数组下一位地址
printf("%d \n",sizeof(&arr[0]+1));//4 第二个元素地址
printf("%d \n",strlen(arr)); //随机值直到遇到 \0
printf("%d \n",strlen(arr+0)); //随机值直到遇到 \0
//printf("%d \n",strlen(*arr)); //相当于strlen(97),error。
//printf("%d \n",strlen(arr[1])); //相当于strlen(97),error。
printf("%d \n",strlen(&arr)); //随机值 从数组地址往后直到\0
printf("%d \n",strlen(&arr+1)); //随机值 从数组下一位地址直到\0
printf("%d \n",strlen(&arr[0]+1)); //随机值 从第二个元素数到\0
return 0;
}
结果展示:

带有指针的字符数组:
例:
int main()
{
char *p = "abcdef";
printf("%d\n",sizeof(p)); //4 指针的大小
printf("%d\n",sizeof(p+1)); //4 首元素地址+1,b的地址,大小为4
printf("%d\n",sizeof(*p)); //1 解引用 一个字符所占的大小
printf("%d\n",sizeof(p[0]));//1 相当于*(p+0),对第一个元素解引用
printf("%d\n",sizeof(&p)); //4 指针的地址
printf("%d\n",sizeof(&p+1));//4 指针下一位的地址
printf("%d\n",sizeof(&p[0]+1));//4 b的地址
printf("%d\n",strlen(p)); //6 字符个数
printf("%d\n",strlen(p+1)); //5 从第二个元素开始直到\0
//printf("%d\n",strlen(*p));//相当于strlen(97),error
//printf("%d\n",strlen(p[0]));//相当于strlen(97),error
printf("%d\n",strlen(&p)); //随机值,指针的地址往后遇到\0
printf("%d\n",strlen(&p+1));//随机值,p的地址下一位往后遇到\0
printf("%d\n",strlen(&p[0]+1));//5 从第二个元素开始数到\0
return 0;
结果:
———————————————————————————————————————————————————
二维数组:
进行二维数组运算时先搞清楚二维数组的储存方式。
将二维数组看成一维数组的方式存储,具有连续性。
例:
int main()
{
int a[3][4]={0};
printf("%d\n",sizeof(a)); //48 12个元素,每个4字节
printf("%d\n",sizeof(a[0][0])); //4
printf("%d\n",sizeof(a[0])); //16 第一行的元素所占字节
printf("%d\n",sizeof(a[0]+1)); //4 其中a[0]表示第一行的首元素,+1就是第一行的第二个元素大小
printf("%d\n",sizeof(a+1)); //4 其中a表示总数组中的首元素,由图得是a[0]一行,+1表示第二行第一个元素
printf("%d\n",sizeof(&a[0]+1)); //4 第一行地址+1,为第二行的地址
printf("%d\n",sizeof(*a)); //16 总数组的首元素所占大小,就是第一行所占的大小
printf("%d\n",sizeof(a[3])); //16 虽然没有第四行,但是默认和前面行数大小相等
return 0;
}
结果:
———————————————————————————————————————————————————
总结:运算大小绕来绕去有点凌乱,但是反复琢磨也能发现其中规律。
当数组名表示整个数组时,只有这两种情况:
1.arr(数组名),当括号里面只有数组名时。
2.&数组名,取数组名地址时。
除了这两种情况,其他数组名出现时,大部分都表示数组的首元素地址。