首先明确 sizeof 和 strlen 的定义
sizeof
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中定义。这是一个依赖于编译系统的值。简单的说,sizeof 是C/C++中的一个操作符,其作用是返回一个对象或类型所占内存的字节数。
strlen
MSDN上的注释为:
Get the length of a string.
strlen是求字符串实际长度的函数,strlen 所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0',sizeof包含‘\0’)。
由此可见,sizeof 在计算长度时是将 ‘\0’ 计算在内的,而strlen则没有将 ‘\0’计算在内。
接下来看 sizeof 和 strlen 关于数组的计算
char arr[] = {'a','b','c','d','e','f' }; printf("%d\n", sizeof(arr));//6 printf("%d\n", sizeof(arr + 0));//4 这里的 arr 其实是代表首元素的地址,所以占4个字节 printf("%d\n", sizeof(*arr));//1 *arr 即指向首元素 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]));//4 printf("%d\n", sizeof(&arr[0] + 1));//4
char arr[] = {'a','b','c','d','e','f' }; printf("%d\n", strlen(arr)); //由于数组中是单个的字符并没有‘\0’,所以strlen在计算时并不知道在什么位置结束,所计算结果是一个随机值,这里假设为10. printf("%d\n", strlen(arr + 0));//10 printf("%d\n", strlen(*arr));// 这里*arr指向数组的首个元素,是char类型,与函数返回类型不匹配,报错 printf("%d\n", strlen(arr[1]));//类型不匹配,报错 printf("%d\n", strlen(&arr));//&arr代表数组的地址,是数组指针,但是在数值上等于首元素的地址,警告 printf("%d\n", strlen(&arr + 1));//&arr+1代表地址加一,跳过该数组,所以10-6=4 printf("%d\n", strlen(&arr[0] + 1));//&arr[0]+1,代表数组第二个元素地址,所以从第二个开始,10-1=9
char arr[] = "abcdef"; //这样定义时,字符串中含有‘\0’,则所求长度是确定的 printf("%d\n", strlen(arr));//6 printf("%d\n", strlen(arr + 0));//6 printf("%d\n", strlen(*arr));//报错 printf("%d\n", strlen(arr[1]));//报错 printf("%d\n", strlen(&arr));//6 printf("%d\n", strlen(&arr + 1));//12 printf("%d\n", strlen(&arr[0] + 1));//5
char *a = "abcdef"; printf("%d\n", strlen(a));//6 printf("%d\n", strlen(a + 1));//5 printf("%d\n", strlen(*a));//报错 printf("%d\n", strlen(a[1]));//报错 printf("%d\n", strlen(&a));//随机值 printf("%d\n", strlen(&a + 1));//随机值 printf("%d\n", strlen(&a[0] + 1));5
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 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 数组可以越界
总结:1、对于一个数组a,只有sizeof(a)和 &a 时,a代表整个数组,其余都表示首元素的地址。
2、二维数组的存储时是线性连续的,可以将二维数组理解为一维数组,只是数组内的元素是一维数组数组(多维数组也可以这样理解)。