一、前置提醒
sizeof()是一个单目操作符,用来计算数据长度,以字节为单位
strlen是C语言标准库定义的一个函数,用来计算字符串的长度,直到空结束字符,但不包括空结束字符。查看源码我们可以知道,strlen要接收一个指针,也就是接收一个地址。
数组名是数组首元素的地址,但是有2个例外:1.sizeof(数组名),这里数组名表示整个数组;2. &数组名,这里数组名表示整个数组,取出的是整个数组的地址。
二、一维数组
先计算打印结果,然后在看后面的答案,笔试!!!不要直接复制到编译器上。
- 整形数组
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; }
int main() { //以下都是32位机情况下的计算结果 int a[] = { 1,2,3,4 }; printf("%d\n", sizeof(a)); //一个int类型占4个字节,4个int类型,打印结果为16 printf("%d\n", sizeof(a + 0)); //a作为数组名不是单独出现的,所以这里a表示首元素地址 //首元素地址+0之后,还是首元素地址 //一个地址的大小为4 printf("%d\n", sizeof(*a)); //a表示首元素地址,*a就是对首元素地址解引用,得到整型1 //一个整型大小为4个字节 printf("%d\n", sizeof(a + 1)); //a + 1得到的是第二个元素的地址 //一个地址的大小为4 printf("%d\n", sizeof(a[1])); //a[1]取到的是第二个元素 //int类型大小为4个字节 printf("%d\n", sizeof(&a)); //取到整个数组的地址,数组的地址也是地址 //一个地址的大小为4 printf("%d\n", sizeof(*&a)); //&a取到的是整个元素的地址,解引用后得到整个数组 //4个int类型,打印结果为16 printf("%d\n", sizeof(&a + 1)); //&a取到一个地址,地址+1后得到的还是一个地址 //一个地址的大小为4 printf("%d\n", sizeof(&a[0])); //操作符[]的优先级比&高 //先a[0],表示数组的第一个元素 //然后取地址&,取到第一个元素的地址 printf("%d\n", sizeof(&a[0] + 1)); //在取到第一个元素的地址上+1,得到第二个元素的地址 return 0; }
- 字符数组
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)); 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)); return 0; }
int main() { //以下都是32位机情况下的计算结果 char arr[] = { 'a','b','c','d','e','f' }; printf("%d\n", sizeof(arr)); //一个char类型大小为1字节,6个char类型,打印6 printf("%d\n", sizeof(arr + 0)); //arr作为数组名不是单独出现的,所以这里arr表示首元素地址 //首元素地址+0之后,还是首元素地址 //一个地址的大小为4字节 printf("%d\n", sizeof(*arr)); //arr表示首元素地址,解引用后得到首元素 //一个char类型大小为1字节 printf("%d\n", sizeof(arr[1])); //表示第二个元素,一个char类型大小为1字节 printf("%d\n", sizeof(&arr)); //取的整个数组的地址,一个地址的大小为4字节 printf("%d\n", sizeof(&arr + 1)); //取到整个数组的地址,然后地址+1,得到另一个地址 printf("%d\n", sizeof(&arr[0] + 1)); //取到首元素的地址后+1,得到第二个元素的地址 //注意:这里是strlen,不是sizeof了,不要继续用sizeof算(doge) printf("%d\n", strlen(arr)); //strlen找到‘\0’才停下来, //但是arr并没有存储‘\0’ //那么strlen会一直找下去,直到找到一个‘\0’为止 //所以打印出来是一个随机值 printf("%d\n", strlen(arr + 0)); //arr+0得到首元素, //然后从首元素开始计算,结果发现怎么还是没有‘\0’ //于是编译器又默默打印一个随机值 printf("%d\n", strlen(*arr)); //*arr解引用得到字符‘a’, //问题出现了,strlen只会接收地址 //所以这行代码是错的 printf("%d\n", strlen(arr[1])); //arr[1]得到字符‘b’,报错 printf("%d\n", strlen(&arr)); //&arr取到整个数组的地址, //BUT这个数组没有‘\0’, //于是编译器双默默打印一个随机值 printf("%d\n", strlen(&arr + 1)); //&arr + 1取到一个地址 //BUT鬼知道‘\0’会在哪儿出现啊 //于是编译器叒默默打印一个随机值 printf("%d\n", strlen(&arr[0] + 1)); //取到首元素地址之后+1,得到第二个元素 //BUT第二元素也不知道‘\0’会在哪儿出现啊 //于是编译器叕默默打印一个随机值 return 0; }
int main() { 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)); 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)); return 0; }
int main() { //以下都是32位机情况下的计算结果 char arr[] = "abcdef"; printf("%d\n", sizeof(arr)); //字符串在存储的时候会在最后加上‘\0’ //sizeof不是strlen,它会计算‘\0’ //所以7个char类型,打印7 printf("%d\n", sizeof(arr + 0)); //arr作为数组名不是单独出现的,所以这里arr表示首元素地址 //首元素地址+0之后,还是首元素地址 //一个地址的大小为4字节 printf("%d\n", sizeof(*arr)); //这里arr表示首元素地址,解引用后得首元素,一个char类型大小为1 printf("%d\n", sizeof(arr[1]));//表示第二个元素,一个char类型大小为1 printf("%d\n", sizeof(&arr));//整个数组的地址,一个地址大小为4 printf("%d\n", sizeof(&arr + 1));//地址+1得到的还是地址,一个地址大小为4 printf("%d\n", sizeof(&arr[0] + 1));//得第二个元素的地址,一个地址大小为4 printf("%d\n", strlen(arr)); //字符串在存储的时候会在最后加上‘\0’ //strlen遇到‘\0’就停止,且不计算‘\0’ //所以打印6 printf("%d\n", strlen(arr + 0)); //得到第一个字符的地址,开始计算长度,遇到‘\0’就停止,打印6 printf("%d\n", strlen(*arr));//strlen要接收地址,报错 printf("%d\n", strlen(arr[1]));//strlen要接收地址,报错 printf("%d\n", strlen(&arr));//取整个数组的地址,打印6 printf("%d\n", strlen(&arr + 1)); //取整个数组的地址,+1跳过这个数组 //这样就不知道哪里有‘\0’了 //打印一个随机值 printf("%d\n", strlen(&arr[0] + 1));//取到‘b’的地址,开始计算,结果为5 return 0; }
三、二维数组
int main() { //二维数组 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])); return 0; }
int main() { //二维数组 int a[3][4] = { 0 }; printf("%d\n", sizeof(a)); //二维数组三行四列,都是int类型 //3 * 4 * 4得48 printf("%d\n", sizeof(a[0][0]));//第一行第一个元素,打印4 printf("%d\n", sizeof(a[0])); //a[0]作为数组名单独放在sizeof内部,表示第一行 //一行存放了4个int类型元素,得16 printf("%d\n", sizeof(a[0] + 1)); //a[0]没有单独放在sizeof内部,也没有取地址,表示第一行第一元素的地址, //+1得到第一行第二个元素的地址,一个地址大小为4 printf("%d\n", sizeof(*(a[0] + 1)));//解引用得到第一行第二个元素,一个int类型大小为4 printf("%d\n", sizeof(a + 1)); //表示首元素地址,代表第一行 //+1得第二行地址,一个地址大小为4 printf("%d\n", sizeof(*(a + 1)));//解引用得到第二行数组,4个int类型大小为16 printf("%d\n", sizeof(&a[0] + 1));//&a[0]取得第一行地址,&a[0] + 1得第二行地址,4 printf("%d\n", sizeof(*(&a[0] + 1)));//对第二行地解引用,得第二行数组,4个int类型大小为16 printf("%d\n", sizeof(*a));//a表示首元素地址,解引用得第一行数组,4个int类型大小为16 printf("%d\n", sizeof(a[3])); //如果存在的话,a[3]表示第四行的数组名, //sizeof不需要它存在,推算出类型进行计算,4个int类型大小为16 return 0; }
四、指针
int main() { 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)); 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)); return 0; }
int main() { char* p = "abcdef"; printf("%d\n", sizeof(p));//p是一个指针,即地址,一个地址大小为4 printf("%d\n", sizeof(p + 1));//地址+1得到的还是一个地址,大小为4 printf("%d\n", sizeof(*p)); //指针P存放的是首元素‘a’的地址 //解引用得到元素‘a’ //一个char类型的大小为1 printf("%d\n", sizeof(p[0]));//p[0]相当于是对p进行解引用,得到元素‘a’,大小为1 printf("%d\n", sizeof(&p)); //指针也是一个变量,他也会开辟一个地址来存储 //取p的地址得到的还是一个地址,大小为4 printf("%d\n", sizeof(&p + 1));//地址+1得到的还是一个地址,大小为4 printf("%d\n", sizeof(&p[0] + 1)); //得到‘a’的地址后 //再对‘a’取地址得到的还是一个地址 //一个地址大小为4 printf("%d\n", strlen(p));//p存放的是‘a’的地址,从‘a’开始计算,结果为6 printf("%d\n", strlen(p + 1));//p+1后得到‘b’的地址,从‘b’开始计算,结果为5 printf("%d\n", strlen(*p));//p解引用后得到‘a’,strlen要接收一个地址,报错 printf("%d\n", strlen(p[0]));//p[0]相当于是对p进行解引用,得到元素‘a’,报错 printf("%d\n", strlen(&p)); //取到指针p的地址,从p的地址开始计算 //但是不知道哪里会有‘\0’,所以打印出一个随机值 printf("%d\n", strlen(&p + 1));//随机值 printf("%d\n", strlen(&p[0] + 1)); //p[0]相当于是对p进行解引用,得到元素‘a’ //再对‘a’取地址,得到‘a’的地址,+1得到‘b’的地址 //从‘b’开始计算,结果为5 return 0; }
就这?就这?就这?不就是两把头发的事情吗?