在之前我们关于数组的内容中,我们已经提出了关于数组名的理解
一般情况下,数组名是数组首元素的地址,但有两个例外:
1.sizeof(数组名)是计算整个数组的大小 2.&数组名是取出的整个数组的地址
sizeof不管后面是啥,只判断这个东西的长度
整型数组
现在给出我们这样的一个数组,然我们进行相关的判断
int a[] = { 1,2,3,4 };
printf("%zd\n", sizeof(a)); //1printf("%zd\n", sizeof(a + 0)); //2printf("%zd\n", sizeof(*a)); //3printf("%zd\n", sizeof(a + 1)); //4printf("%zd\n", sizeof(a[1])); //5printf("%zd\n", sizeof(&a)); //6printf("%zd\n", sizeof(*&a)); //7printf("%zd\n", sizeof(&a + 1)); //8printf("%zd\n", sizeof(&a[0])); //9printf("%zd\n", sizeof(&a[0] + 1)); //10
式子一:sizeof+数组,整个数组的长度,单位是字节,因此是4 * 4 = 16
式子二:并不是sizeof中只有数组,因此此时是数组首元素的地址,+0还是首元素的地址,地址的字节是4/8
式子三:a是首元素地址,*a是首元素,大小4
式子四:第二个元素的地址,4/8
式子五:a[1]是第二个元素,4
式子六:取出的是数组的地址,4/8
式子七:取出了数组的地址,解引用后是整个数组a,因此是16
式子八:取出整个数组的地址,跳过这个数组后的地址,4/8
式子九:取出首元素的地址,4/8
式子十:取出第二个元素的地址,4/8
字符串数组(一)
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr)); //1printf("%d\n", sizeof(arr + 0)); //2printf("%d\n", sizeof(*arr)); //3printf("%d\n", sizeof(arr[1])); //4printf("%d\n", sizeof(&arr)); //5printf("%d\n", sizeof(&arr + 1)); //6printf("%d\n", sizeof(&arr[0] + 1)); //7
这个数组只有六个元素
式子一:整个数组的长度,1 * 6 = 6
式子二:第一个元素的地址,4/8
式子三:arr是一个元素的地址,*arr是第一个元素,是char类型,1
式子四:第二个元素,1
式子五:取出整个数组的地址,地址的大小是4/8
式子六:取出整个数组的地址,跳过了一个数组,4/8
式子七:取出第二个元素的地址,4/8
那么,对于strlen呢?
strlen是判断字符串长度的,是从括号里的地址开始,直到\0位置为止
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr)); //1printf("%d\n", strlen(arr + 0)); //2printf("%d\n", strlen(*arr)); //3printf("%d\n", strlen(arr[1])); //4printf("%d\n", strlen(&arr)); //5printf("%d\n", strlen(&arr + 1)); //6printf("%d\n", strlen(&arr[0] + 1)); //7
式子一:arr代表数组首元素的地址,由于无\0,故是随机值
式子二:数组首元素的地址,随机值
式子三:数组的首元素,'a'- -> 97,相当于取97地址,err,读取位置访问冲突,报错
式子四:数组的第二个元素,'b'-->98,err
式子五:取出整个数组的地址,数组的地址就是首元素的地址,随机值
式子六:跳过一个数组以后的地址,随机值
式子七:从第二个元素的地址开始,随机值
那么对于另一种字符串数组呢?
字符串数组(二)
char arr[] = "abcdef";
printf("%d\n", sizeof(arr)); //1printf("%d\n", sizeof(arr + 0)); //2printf("%d\n", sizeof(*arr)); //3printf("%d\n", sizeof(&arr)); //4printf("%d\n", sizeof(&arr+1)); //5printf("%d\n", sizeof(&arr[0]+1)); //6
式子一:计算数组的长度,不要忘记隐藏的\0,7
式子二:数组首元素的地址,大小4/8
式子三:arr是数组的首元素地址,*arr是数组的首元素,char类型,1
式子四:取出整个数组的地址,大小4/8
式子五:跳过一个数组后的地址,4/8
式子六:第二个元素的地址,4/8
char arr[] = "abcdef";
printf("%d\n", strlen(arr)); //1
printf("%d\n", strlen(arr+0)); //2
printf("%d\n", strlen(*arr)); //3
printf("%d\n", strlen(arr[1])); //4
printf("%d\n", strlen(&arr)); //5
printf("%d\n", strlen(&arr+1)); //6
printf("%d\n", strlen(&arr[0]+1)); //7
式子一:长度为6
式子二:首元素的地址,向后数,也是6
式子三:*arr代表首元素,'a'-->97,err
式子四:数组的第二个元素,'b'-->98,err
式子五:取出arr的地址,6
式子六:跳过一个数组后的地址,随机值
式子七:从第二个元素开始的地址,计算5
字符串数组(三)
char* p = "abcdef";
printf("%d\n", sizeof(p));//p是指针变量,计算的指针变量的大小,4/8字节
printf("%d\n", sizeof(p + 1));//'b'的地址,4/8
printf("%d\n", sizeof(*p));//p的类型是char*,*p是char,a,1
printf("%d\n", sizeof(p[0]));//p[0]-->*(p+0)-->*p-->'a',1
printf("%d\n", sizeof(&p));//取出的是p的地址,4/8
printf("%d\n", sizeof(&p + 1));//跳过p指针变量后的地址,是4/8
printf("%d\n", sizeof(&p[0] + 1));//第二个元素的地址
式子一:p是指针变量,计算指针变量的大小,4/8
式子二:'b'的地址,4/8
式子三:p是指针,*p是a,大小1
式子四:a,大小是1
式子五:p是指针,&p是二级指针,也是指针,4/8
式子六:跳过p后的地址,4/8
式子七:第二个元素的地址
char* p = "abcdef";
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5
printf("%d\n", strlen(*p));//97,err
printf("%d\n", strlen(p[0]));//err
printf("%d\n", strlen(&p));//&p是指针变量p的地址,与字符串"abcdef"关系不大
//从p这个指针变量起始位置开始数的,p的地址是什么不知道,随机值
printf("%d\n", strlen(&p + 1));//随机值
printf("%d\n", strlen(&p[0] + 1));//5
式子一:p是指针变量,指向a的位置,6
式子二:指向b,5
式子三:*p是字符a-->97,err
式子四:也是字符a
式子五:二级指针,不清楚大小,随机值
式子六:二级指针后跳过p,随机值
式子七:从第二个元素地址开始计算,5
二维数组
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//a是数组名,单独放在sizeof内部,计算数组大小48
printf("%d\n", sizeof(a[0][0]));//第一行的第一个元素,4个字节
printf("%d\n", sizeof(a[0]));//第一行的数组名,数组名单独放在sizeof,计算数组大小,16
printf("%d\n", sizeof(a[0] + 1));//a[0]并没有单独放在内部,这里的a[0]是数组的首元素地址//等价于&a[0][0],+1后是a[0][1]的地址,4/8
printf("%d\n", sizeof(*(a[0] + 1)));//第一行第二个元素,4
printf("%d\n", sizeof(a + 1));//a作为数组没有单独放在内部,a表示数组首元素地址//二维数组首元素的地址就是第一行的地址,跳过一行指向第二行//a+1是数组指针,指针大小4/8
printf("%d\n", sizeof(*(a + 1)));//*(a + 1)代表第二行 - 16//*(a + 1) == a[1],是第二行的数组名
printf("%d\n", sizeof(&a[0] + 1));//a[0]是第一行数组名,&a[0]第一行的地址,//+1,跳过第一行,第二行的地址,4/8个字节
printf("%d\n", sizeof(*(&a[0] + 1)));//第二行,*(&a[0] + 1) == *(a + 1),16
printf("%d\n", sizeof(*a));//a代表第一行的地址,*a代表第一行,16
printf("%d\n", sizeof(a[3]));//a[3]无需真实访问,仅仅通过类型的推断就能算出长度//a[3]是第四行的数组名,大小单独放在sizeof内部,计算第四行的大小,16
式子一:计算整个数组的大小 4 * 12
式子二:计算第一行首元素,int类型,4
式子三:a[0]代表第一行,可以理解为一维数组,大小是16
式子四:a[0]代表的是地址,+1后也是地址,4/8
式子五:第一行第二个元素,4
式子六:第二行的地址,4/8
式子七:第二行,4 * 4 = 16
式子八:第二行的地址,4/8
式子九:第二行,16
式子十:第一行,16
式子十一:被认为了第四行,尽管没有,但不会实际运算,只会根据他的类型 int [4]判断出这一行可能是4个元素,大小是16
感谢您的观看
总结
sizeof + 地址 = 4/8
strlen一般来说只能加地址