数组名的理解 : 数组名就是首元素地址
但是有两个例外:
1. sizeof(数组名)这里的数组名表示整个数组的大小,sizeof(数组名)计算的是整个数组的大小,单位是字节
2. &数组名 这里的数组名表示整个数组 ,&数组名取出的是数组的地址
目录
[三 .笔试题 ( 3 )](#三 .笔试题 ( 3 ))
[四. 笔试题 ( 4 )](#四. 笔试题 ( 4 ))
一.笔试题 ( 1 )
博主个人建议 : 自己先做一遍,看看哪个做错了,然后再看博主的解释
做对的题,自己想想因为什么得这个数,看看与博主的解释一样不
sizeof的解释
sizeof ()是C语言中常用的运算符,可以计算操作数的大小。. sizeof的结果是无符号整数类型,通常用size_t表示。. sizeof可以应用于各种数据类型,包括基本的数据类型,例如整数和浮点类型,指针类型和符合数据类型,结构体等等。
cs
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;
}
博主自己做了一遍 printf("%d\n", sizeof(&a)); 我认为这个打印的是16 因为 ,&数组名 ,这里的数组名表示整个数组 ,但是事实上我只想对了一半
&a - 是取出数组的地址,但是数组的地址也是地址,是地址就是4/8个Byte (在32位下是4个字节,64位下是8个字节) 数组的地址 和 数组首元素的地址 的本质区别是类型的区别,并非大小的区别
上面的代码解释如下:
cs
int main()
{
//一维数组
int a[] = { 1,2,3,4 };//4个元素,每个元素使int类型(4个字节)
printf("%d\n", sizeof(a));
//数组名a单独放在sizeof内部,数组名表示整个数组,计算的是整个数组的大小单位是字节,是16字节
printf("%d\n", sizeof(a + 0));
//a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址,a+0还是首元素的地址
//是地址大小就是4/8 Byte
printf("%d\n", sizeof(&a));
// &a - 是取出数组的地址,但是数组的地址也是地址,是地址就是4/8个Byte
//数组的地址 和 数组首元素的地址 的本质区别是类型的区别,并非大小的区别
printf("%d\n", sizeof(*&a));
//对数组指针解引用访问一个数组的大小,单位是字节
//sizeof(*&a) --- sizeof(a)
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]是首元素的地址,&a[0]+1就是第二个元素的地址,大小4/8个字节
return 0;
}
拓展:&a[0] + 1是第二个元素的地址,大小 4/8 个字节
同样表示第二个元素地址的写法还有 &a[1] &a[0]+1 a+1
二.笔试题 ( 2 )
指针变量的大小和类型无关,不管什么类型的指针变量,大小都是4/8个字节
指针变量是用来存放地址的,地址存放需要多大空间,指针变量的大小就是几个字节
32位环境下,地址是32个二进制位,需要4个字节,所以指针变量的大小就是4个字节
64位环境下,地址是64个二进制位,需要8个字节,所以指针变量的大小就是8个字节
strlen函数的解释
strlen函数,只有遇到 ' \0 ' 时才停止
cs
#include <string.h>
int main()
{
//字符数组
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));
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;
}
自己要先做一遍!!!!!!!!!!!!!!!!再看解释
博主,自己做的时候,printf("%d\n", sizeof(*arr));
我认为它应该是4个字节,又是想对了一半
arr是首元素的地址,正常来说地址是4/8个字节,但是它是*arr
*arr就是第一个元素所以它是 1 个字节
cs
int main()
{
//字符数组
char arr[] = { 'a','b','c','d','e','f' };//6
printf("%d\n", strlen(arr));//随机值,arr是首元素的地址
printf("%d\n", strlen(arr + 0));//随机值,arr是首元素的地址, arr+0还是首元素的地址
printf("%d\n", strlen(*arr));//err,arr是首元素的地址, *arr就是首元素 - 'a' - 97
//站在strlen的角度,认为传参进去的'a'-97就是地址,97作为地址,直接进行访问,就是非法访问
printf("%d\n", strlen(arr[1]));//err, 'b' - 98
printf("%d\n", strlen(&arr));//随机值
//&arr -- char (*)[6]
//const char*
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//随机值
printf("%d\n", sizeof(arr));//6 数组名arr单独放在sizeof内部,计算的是整个数组的大小,单位是字节
printf("%d\n", sizeof(arr + 0));//arr是首元素的地址==&arr[0],是地址就是4/8个字节
printf("%d\n", sizeof(*arr));//arr是首元素的地址,*arr就是首元素,大小就是1Byte
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//&arr是数组的地址,sizeof(&arr)就是4/8个字节
printf("%d\n", sizeof(&arr + 1));//&arr+1 是跳过数组后的地址,是地址就是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是地址就是4/8Byte
return 0;
}
三 .笔试题 ( 3 )
cs
int main()
{
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));*/
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;
}
自己要先做一遍!!!!!!!!!!!!!!!!再看解释 ( 重要的事情说三遍)
printf("%d\n", sizeof(arr));我认为这个是 6 但是结果是7,因为我少算了一个 ' \0 '
|---------------------|
| a b c d e f \0 共7个 |
(每个笔试题必须要错一个,脑袋疼)
cs
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//字符串长度,遇到'\0'停止所以是6
printf("%d\n", strlen(arr + 0));//字符串长度,遇到'\0'停止,6
printf("%d\n", strlen(*arr));//err 传参错误,应该传的是字符串的地址
printf("%d\n", strlen(arr[1]));//传参错误,道理同上
printf("%d\n", strlen(&arr));//数组首元素地址,6
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//从b开始往后所以答案是5
printf("%d\n", sizeof(arr));//整个数组包括'\0'所以是7
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;
}
四. 笔试题 ( 4 )
cs
int main()
{
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));
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));
return 0;
}
我这次错了很多 (可能是眼睛太大了,没看见是 char* p )
大家在看东西的时候一定要观察仔细!!!!
printf("%d\n", strlen(p + 1));首元素地址+1,从b开始所以应该是5
printf("%d\n", strlen(&p) 随机值,
printf("%d\n", strlen(&p + 1));随机值
大家有什么不懂的可以去看笔试题 ( 3 )的解释
cs
printf("%d\n", strlen(p)); //6
printf("%d\n", strlen(p + 1)); //5
printf("%d\n", strlen(*p)); //err
printf("%d\n", strlen(p[0])); //err
printf("%d\n", strlen(&p)); //随机值
printf("%d\n", strlen(&p + 1));//随机值
printf("%d\n", strlen(&p[0] + 1)); //5
printf("%d\n", sizeof(p));//4/8 计算的是指针变量的大小
printf("%d\n", sizeof(p + 1));//p+1还是地址,大小是4/8个字节
printf("%d\n", sizeof(*p));//1个字节, *p == 'a'
printf("%d\n", sizeof(p[0]));//1个字节, p[0]--> *(p+0) --> *p == 'a';
printf("%d\n", sizeof(&p));//4/8个字节,&p 是地址
printf("%d\n", sizeof(&p + 1));//&p是地址,&p+1还是地址,是地址就是4/8个字节
printf("%d\n", sizeof(&p[0] + 1));
五.笔试题 ( 5 )
cs
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]));
cs
int main()
{
int a[3][4] = { 0 };
printf("%zd\n", sizeof(a));//48-数组名a单独放在了sizeof内存,表示整个数组,sizeof(a)计算的是数组的大小,单位是字节
printf("%zd\n", sizeof(a[0][0]));//4-a[0][0]是数组的第一行第一个元素,这里计算的就是一个元素的大小,单位是字节
printf("%zd\n", sizeof(a[0]));//16 - a[0]是第一行这个一维数组的数组名,数组名单独放在了sizeof内部
//a[0]就表示整个第一行这个一维数组,sizeof(a[0])计算的整个第一行这个一维数组的大小
printf("%zd\n", sizeof(a[0] + 1));//4/8 - a[0]并非单独放在sizeof内部,也没有&,所以a[0]表示第一行这个一维数组首元素的地址
//也就是第一行第一个元素的地址
//a[0] <---> &a[0][0]
//a[0]+1 ---> &a[0][1]
printf("%zd\n", sizeof(*(a[0] + 1)));//4 - a[0] + 1是第一行第二个元素的地址,*(a[0] + 1))就是第一行第二个元素
//
printf("%zd\n", sizeof(a + 1));//4/8
//a 作为二维数组的数组名,并没有单独放在sizeof内部,也没有&,a就是数组首元素的地址,也就是第一行的地址, a 的类型是 int(*)[4]
//a+1 就是第二行的地址,类型是:int(*)[4]
//
printf("%zd\n", sizeof(*(a + 1)));//16 a+1是第二行的地址,*(a+1)就是第二行,计算的就是第二行的大小
//另外一个角度理解:*(a+1) -- a[1]
//sizeof(a[1]) - a[1]这个第二行的数组名,单独放在了sizeof内部,计算的是第二行的大小
printf("%zd\n", sizeof(&a[0] + 1));//4/8
//a[0]是第一行的数组名,&a[0]取出的是数组的地址,取出的是第一行这个一维数组的地址,类型就是int(*)[4]
//&a[0]+1 就是第二行的地址,类型就是int(*)[4]
printf("%zd\n", sizeof(*(&a[0] + 1)));//*(&a[0] + 1)得到的就是第二行,计算的就是第二行的大小
printf("%zd\n", sizeof(*a));//16
//a表示数组首元素的地址,也就是第一行的地址
//*a 就是第一行,也就相当于是第一行的数组名
//*a--> *(a+0) -- a[0]
//
printf("%zd\n", sizeof(a[3]));//16-不会越界,
//a[3] -- arr[0]
//int [4] int [4]
//int a = 10;
//sizeof(a);//sizeof(int)
//表达式 有2个属性:值属性,类型属性
//2+3 = 5
// = int
return 0;
}
新人博主,如果有地方解释的不对或者不清晰,麻烦大佬们海涵,如果可以麻烦从评论区指出,我一定会加以修改,万分感谢
最后麻烦大佬们动一下发财的小手一键三连,千万分感谢