我们前面学了四个部分了,如果没有看前面的建议可以看一下前面的~~
在学习操作符的时候,我们学习了sizeof , sizeof 计算变量所占内存内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。
我们就来开始学习了解sizeof~~
size_t其实专门是设计给sizeof的,表示sizeof的返回值类型sizeof计算的不可能是负数吧,所以size_t是为sizeof来设计的~~列如:
int main()
{
int a = 10;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(int));
return 0;
}


sizeof 只关注占用内存空间的大小,不在乎内存中存放什么数据,我们一会来详细看~~strlen 是C语言库函数,功能是求字符串长度。函数原型如下:
size_t strlen ( const char * str );
它统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数。
strlen 函数会一直向后找\0 字符,直到找到为止,所以可能存在越界查找。
我们来看下面的代码
int main()
{
char arr2[] = "abc";
printf("%d\n", strlen(arr2));
return 0;
}
3
\0,strlen是统计\0之前的字符串的个数,结果是3
\0会算出几呢?char arr2[] = "ab\0c";
printf("%d\n", strlen(arr2));
3
\0它的结果是什么呢?char arr1[] = { 'a', 'b', 'c' };
printf("%d\n", strlen(arr1));
\0。

strlen和sizeofstrlen:
sizeof:
string.h\0之前字符的个数\0,如果没有\0,就会持续往后找,可能会越界short s = 10;
int i = 2;
int n = sizeof(s = i + 4);
printf("%d\n", n);
printf("%d\n", s);

为什么是2和10呢?我们来分析一下~~
创建了一个短整型s,占两个字节,i是整形,占四个字节
这里的i+4得出的结果我要放到s类型,我一个4个整形的放到两个整形的空间,这要发生截断,截断之后就是s说了算,所以就是2个字节。
那么第二个,表达式放到sizeof内部不会真实计算的,不参与计算!!!所以原来的值就会打印什么值~~
如果还没有理解的话,我们来看一些笔试题,来加深一下印象~~
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
return 0;
}
sizeof内部单独放了一个数组名,数组名表示整个数组的大小,数组内有4个元素,每个元素4个字节,所以就是16printf("%d\n", sizeof(a));
&,所以a就是首元素的地址,是地址,大小就是4/8个字节printf("%d\n", sizeof(a + 0));
a[0],大小就是4个字节printf("%d\n", sizeof(*a));
4/8printf("%d\n", sizeof(a + 1));
4printf("%zd\n", sizeof(a[1]));
&a 取出的是数组的地址,但是数组的地址也是地址,是地址大小就是4 / 8 个字节printf("%zd\n", sizeof(&a));
int(*p)[4] = &a,*p访问一个数组的大小,p+1就是跳过一个数组的大小,结果是16printf("%d\n", sizeof(*&a));
4/8printf("%zd\n", sizeof(&a + 1));
4/8printf("%zd\n", sizeof(&a[0]));
4/8printf("%zd\n", sizeof(&a[0] + 1));


int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
return 0;
}
6printf("%d\n", sizeof(arr));
4/8个字节printf("%d\n", sizeof(arr + 0));
1个字节printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
4/8printf("%d\n", sizeof(&arr));
4/8printf("%d\n", sizeof(&arr + 1));
4/8printf("%d\n", sizeof(&arr[0] + 1));


char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
\0之前的元素个数所以就是随机值printf("%d\n", strlen(arr));
随机值~~printf("%d\n", strlen(arr+0));
a,ASCLL码值是97,97传给strlen,会把97当成个地址,会非法访问,结果会报错
printf("%d\n", strlen(*arr));
报错printf("%d\n", strlen(arr[1]));
随机值printf("%d\n", strlen(&arr));
随机值printf("%d\n", strlen(&arr+1));
随机值printf("%d\n", strlen(&arr[0]+1));

abcdef\0,这里面有\0~~char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
7printf("%d\n", sizeof(arr));
4/8个字节printf("%d\n", sizeof(arr+0));
1字节printf("%d\n", sizeof(*arr));
1字节printf("%d\n", sizeof(arr[1]));
4/8个字节printf("%d\n", sizeof(&arr));
4/8个字节printf("%d\n", sizeof(&arr+1));
4/8个字节printf("%d\n", sizeof(&arr[0]+1));

char arr[] = "abcdef";
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
6printf("%d\n", strlen(arr));
6printf("%d\n", strlen(arr+0));
报错,会非法访问printf("%d\n", strlen(*arr));
非法访问~~printf("%d\n", strlen(arr[1]));
6printf("%d\n", strlen(&arr));
随机值printf("%d\n", strlen(&arr+1));
5printf("%d\n", strlen(&arr[0]+1));

p存放的是这个字符串a的地址char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
4/8个字节printf("%d\n", sizeof(p));
4/8个字节printf("%d\n", sizeof(p+1));
*p 是首字符,大小是1字节printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
32位下

64位下

char *p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));
6printf("%d\n", strlen(p));
char*,+1跳过的就是一个char类型的数据,所以就来到了字符'b'的地址处,向后找\0的话就最后的结果即为 5printf("%d\n", strlen(p+1));
*p取到的就是字符'a',strlen就会把字符a的ascll码值当地址传过去了,会产生非法访问,结果是errprintf("%d\n", strlen(*p));
*p == *(p+0) == p[0]printf("%d\n", strlen(p[0]));
char*从p所占空间的起始位置开始查找的,它不知道什么时候会遇到\0,所以就会是随机值printf("%d\n", strlen(&p));
char**,+1会跳过一个char*类型的数据,它指向了字符串末尾的这个位置,从这里向后去进行找\0,也是不知道什么时候会遇到,所以最后的结果还是随机值printf("%d\n", strlen(&p+1));
'b',结果也就是5printf("%d\n", strlen(&p[0]+1));

最后我们再来看二维数组,也是比较难的一部分
int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));
48printf("%d\n", sizeof(a));
4个字节printf("%d\n", sizeof(a[0][0]));
a[0]为第一行的数组名,而且它是单独放在sizeof()内部的,计算的是第一行这一整行的大小,里面有4个元素,每个元素都是4个字节,那么结果即为16printf("%d\n", sizeof(a[0]));
a[0][1]的地址,地址的大小是4/8个字节printf("%d\n", sizeof(a[0] + 1));
a[0] + 1是第一行第二个元素a[0][1]的地址,*(a[0] + 1)就是第一行第二个元素,大小是4个字节printf("%d\n", sizeof(*(a[0] + 1)));
a没有单独放在sizeof内部,没有&,数组名a就是数组首元素的地址,也就是第一行的地址,a+1,就是第二行的地址,也就是等价于a -- int(*)[4] ---->a+1 -- int(*)[4]printf("%d\n", sizeof(a + 1));
16printf("%d\n", sizeof(*(a + 1)));
*(a + 1) ,计算的是第二行的元素大小,结果是16printf("%d\n", sizeof(a[1]));
+1的话也会跳过整个数组,此时也就来到了第二行,那么取到的便是第二行的地址,地址的大小即为 4/8个字节printf("%d\n", sizeof(&a[0] + 1));
16printf("%d\n", sizeof(*(&a[0] + 1)));
*a就是一行的 等价于*(a+0) == a[0]printf("%d\n", sizeof(*a));
这个二维数组不是只有三行吗,第三行的数组名为a[2],那a[3]不是越界了吗?
要知道,对于任何一个表达式来说具有2个属性,一个是【值属性】,一个是【类型属性】
例如3 + 5 = 8,它的值属性就是数字8,类型属性即为int但对于【sizeof()】来说,它在计算的时候只需要知道【类型属性】就可以了,类似我们之前写过的sizeof(int)、sizeof(char)等等,对这些内置类型就可以计算出它的大小,并没有去实际地创造出空间
那么对于下面这个a[3]来说,虽然看上去存在越界,但是sizeof()并不关心你有没有越界,而是知道你的类型即可,那么a[3]便是二维数组的第四行,虽然没有第四行,但是类型是确定的,那么大小就是确定的,计算sizeof(数组名)计算的是整个数组的大小,结果便是16
printf("%d\n", sizeof(a[3]));
