strlen是库函数,包含在头文件的<string.h>中,主要有2点:
1.strlen关注的字符串中\0的为止,计算的是\0之前出现了多少个字符 2.strlen指针对字符串
sizeof是操作符,是有优先级的(第2级,比括号小),主要有两点
1.sizeof只关注占用空间的大小,单位是字节, 2.sizeof不关注类型,任意类型都可以,可求不同类型变量所占空间字节大小
下面是综合习题供加深对strlen和sizeof的理解(注意:数组名只有单独在sizeof内部,或&数组ming的时候才代表整个数组,其他时候数组名只代表首元素的地址)
(1)对于整形数组 a[ ] = {1,2,3,4};
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//数组名单独在sizeof里面是整个数组大小,4*4 = 16
printf("%d\n", sizeof(a + 0));//数组名没有单独放在sizeof里面或&啊,为首元素地址,地址+0还是地址,4/8;
printf("%d\n", sizeof(*a));//数组名不是单独放的,解引用为1,是int故是4
printf("%d\n", sizeof(a + 1));//类比二,这个是int 2的地址,4/8
printf("%d\n", sizeof(a[1]));//a[1]是2,整形是4个字节
printf("%d\n", sizeof(&a)); //整个数组的地址,是个数组指针,还是指针4/8
printf("%d\n", sizeof(*&a));//变成了a,就是单独放了,16
//&a是数组的地址,它的类型是int(*)[4]数组指针,如果解引用,访问的就是4个int的数组,大小是16个字节
printf("%d\n", sizeof(&a + 1));//&a是数组的地址,&a+1 跳过整个数组后的地址,是地址就是4/8
printf("%d\n", sizeof(&a[0]));//&a[0]取出数组第一个元素的地址,是地址就是4/8
printf("%d\n", sizeof(&a[0] + 1));//&a[0]+1就是第二个元素的地址,是地址大小就是4/8个字节
(2) 对于字符数组char arr[ ] = { 'a','b','c','d','e','f' };
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//arr是首元素的地址,但是arr数组中没有\0,计算的时候就不知道什么时候停止,结果是:随机值
printf("%d\n", strlen(arr + 0));//arr是首元素的地址,arr+0还是首元素的地址,结果是:随机值
printf("%d\n", strlen(*arr)); //err,strlen需要的是一个地址,从这个地址开始向后找字符,直到\0,统计字符的个数。但是*arr是数组的首元素,也就是'a',这是传给strlen的就是'a'的ascii码值97,strlen函数会把97作为起始地址,统计字符串,会形成内存访问冲突,故错误
printf("%d\n", strlen(arr[1]));//err 和上一个一样,内存访问冲突,这个是b的ascii
printf("%d\n", strlen(&arr));//&arr是arr数组的地址,虽然类型和strlen的参数类型有所差异,但是传参过去后,还是从第一个字符的位置向后数字符,结果还是随机值。
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//随机值
printf("%d\n", sizeof(arr));//arr作为数组名单独放在sizeof内部,计算的整个数组的大小,单位是字节,6
printf("%d\n", sizeof(arr + 0));//arr就是首元素的地址,arr+0还是首元素的地址,地址大小就是4/8
printf("%d\n", sizeof(*arr));//arr就是首元素的地址,*arr就是首元素,是一个字符,大小是一个字节,1
printf("%d\n", sizeof(arr[1]));//arr[1]就是数组的第二个元素,是一个字符,大小是1个字节
printf("%d\n", sizeof(&arr));//&arr取出的是数组的地址,数组的地址也是地址,地址就是4/8个字节
printf("%d\n", sizeof(&arr + 1));//&arr取出的是数组的地址,&arr+1,跳过了整个数组,&arr+1还是地址,地址就是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]是第一个元素的地址,&arr[0]+1就是第二个元素的地址,地址就是4/8个字节
(3)对于char arr[] = "abcdef";
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//数组名不是单独放sizeof内部也不是 &arr,故是首元素地址,strlen只关注‘\0’,结果为6
printf("%d\n", strlen(arr + 0));//首元素的地址加0,还是首元素的地址,向后访问到\0,结果为6
printf("%d\n", strlen(*arr));//报错,用的是a的ascii码,访问冲突
printf("%d\n", strlen(arr[1]));//同上,b的ascii码,错误。
printf("%d\n", strlen(&arr));//类型不同报警告,但地址相同,依然指向首元素的地址处,strlen直接强制访问,为6。
printf("%d\n", strlen(&arr + 1));//随机值,&arr是指向整个数组的地址,+1跳过整个数组,但依然是地址。访问直到\0,后面不确定,故为随机值。
printf("%d\n", strlen(&arr[0] + 1));//5,&arr[0]为a的地址,+1为b的地址,向后到\0,结果为5
printf("%d\n", sizeof(arr));//包括了\0,7,sizeof求的是变量占用的字节大小,\0也为一个字节
printf("%d\n", sizeof(arr + 0));//arr为首元素,地址加0还是地址,4/8
printf("%d\n", sizeof(*arr));//,*arr=a, a的类型是char,1
printf("%d\n", sizeof(arr[1]));//b为char,1
printf("%d\n", sizeof(&arr));//取整个数组的地址,仍然是地址,4/8
printf("%d\n", sizeof(&arr + 1));//整个数组的地址+1,跳过数组arr后仍然是地址,4/8
printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]为a的地址,4/8
(4)对于char* p = "abcdef";
char* p = "abcdef";
printf("%d\n", strlen(p));//p中存放的是'a'的地址,strlen(p)就是从'a'的位置向后求字符串的长度,长度是6
printf("%d\n", strlen(p + 1));//p+1是'b'的地址,从b的位置开始求字符串长度是5
printf("%d\n", strlen(*p));//err,*p=a,但srelen的参数要求为地址,故采用的是a的ascii码值,造成错误访问。
printf("%d\n", strlen(p[0]));//err,同上。
printf("%d\n", strlen(&p));//随机值,p是指针,是a的地址,&p是p的地址,后面无法确认\0
printf("%d\n", strlen(&p + 1));//随机值,同上,p的地址+1,无法确认后面的\0
printf("%d\n", strlen(&p[0] + 1));//p[0] -> *(p+0) -> *p ->'a' ,&p[0]就是首字符的地址,&p[0]+1就是第二个字符的地址,从第2 字符的位置向后数字符串,长度是5
printf("%d\n", sizeof(p)); //p是一个指针变量,sizeof(p)计算的就是指针变量的大小,4 / 8个字节
printf("%d\n", sizeof(p + 1));//p是指针变量,是存放地址的,p+1也是地址,地址大小就是4/8字节
printf("%d\n", sizeof(*p));//*p访问的是1个字节,*p=a,类型是char
printf("%d\n", sizeof(p[0]));//p[0]--> *(p+0) -> *p 1个字节
printf("%d\n", sizeof(&p));//&p也是地址,是地址就是4/8字节,&p是二级指针
printf("%d\n", sizeof(&p + 1)); //&p是地址, + 1后还是地址,是地址就是4 / 8字节
&p + 1,是p的地址+1,在内存中跳过p变量后的地址
//printf("%d\n", sizeof(&p[0] + 1));//p[0]就是a,&p[0]就是a的地址,&p[0]+1就是b的地址,是地址就是4/8字节
(5)对于 int a[3][4] = { 0 };
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//数组名单独放在sizeof内部,计算的是整个数组的大小,12*4=48
printf("%d\n", sizeof(a[0][0]));//首元素的大小,是int类型,4
printf("%d\n", sizeof(a[0]));//a[0]表示第一行的数组名,a[0]作为数组名单独放在sizeof内部,计算的是第一行的大小,4*4=16。
printf("%d\n", sizeof(a[0] + 1));//a[0]不是单独放在sizeof内部,故为首元素地址+1,仍是地址, 4/8,是第一行第2个元素的地址
printf("%d\n", sizeof(*(a[0] + 1)));//a[0] + 1是第一行第2个元素的地址,解引用为第一行第二个元素0,类型是int,4个字节
printf("%d\n", sizeof(a + 1));//a不是单独放,为首元素a[0]的地址,+1为第二行a[1]的地址,4/8
printf("%d\n", sizeof(*(a + 1)));//a+1为第二行a[1]的地址,解引用为a[1],单独放为第二行元素,4*4 = 16
printf("%d\n", sizeof(&a[0] + 1));//&a[0]为第一行的地址,+1为第二行,&a[0] + 1等同于a+1,结果为4/8
printf("%d\n", sizeof(*(&a[0] + 1)));//第二行的地址解引用为第二行,也就是a[1],结果4*4 = 16
printf("%d\n", sizeof(*a));//a不是单独放在sizeof,*a = a[0] 仍是数组名,这是单独放,4*4=16
printf("%d\n", sizeof(a[3]));//这里是越界访问,但是sizeof注重求不同类型变量所占空间的大小,a[3] 是第四行的数组名,单独放在sizeof内部,4*4 = 16
以上是本章的全部内容,均是本人的一些浅薄见解
自己深知自我的知识储备还比较有限
如有理解不恰当之处,望各位指正
|