数组名的理解 : 数组名就是首元素地址
但是有两个例外:
1. sizeof(数组名)这里的数组名表示整个数组的大小,sizeof(数组名)计算的是整个数组的大小,单位是字节
2. &数组名 这里的数组名表示整个数组 ,&数组名取出的是数组的地址
目录
一.笔试题 ( 1 )
sizeof的解释
二.笔试题 ( 2 )
strlen函数的解释
三 .笔试题 ( 3 )
四. 笔试题 ( 4 )
五.笔试题 ( 5 )
一.笔试题 ( 1 )
博主个人建议 : 自己先做一遍,看看哪个做错了,然后再看博主的解释
做对的题,自己想想因为什么得这个数,看看与博主的解释一样不
sizeof的解释
sizeof ()是C语言中常用的运算符,可以计算操作数的大小。. sizeof的结果是无符号整数类型,通常用size_t表示。. 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;
}
博主自己做了一遍 printf("%d\n", sizeof(&a)); 我认为这个打印的是16 因为 ,&数组名 ,这里的数组名表示整个数组 ,但是事实上我只想对了一半
&a - 是取出数组的地址,但是数组的地址也是地址,是地址就是4/8个Byte (在32位下是4个字节,64位下是8个字节) 数组的地址 和 数组首元素的地址 的本质区别是类型的区别,并非大小的区别
上面的代码解释如下:
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 Byteprintf("%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 ' 时才停止
#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 个字节
int main()
{//字符数组char arr[] = { 'a','b','c','d','e','f' };//6printf("%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' - 98printf("%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就是首元素,大小就是1Byteprintf("%d\n", sizeof(arr[1]));//1printf("%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/8Bytereturn 0;
}
三 .笔试题 ( 3 )
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个 |
(每个笔试题必须要错一个,脑袋疼)
int main()
{char arr[] = "abcdef";printf("%d\n", strlen(arr));//字符串长度,遇到'\0'停止所以是6printf("%d\n", strlen(arr + 0));//字符串长度,遇到'\0'停止,6printf("%d\n", strlen(*arr));//err 传参错误,应该传的是字符串的地址printf("%d\n", strlen(arr[1]));//传参错误,道理同上printf("%d\n", strlen(&arr));//数组首元素地址,6printf("%d\n", strlen(&arr + 1));//随机值printf("%d\n", strlen(&arr[0] + 1));//从b开始往后所以答案是5printf("%d\n", sizeof(arr));//整个数组包括'\0'所以是7printf("%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 )
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 )的解释
printf("%d\n", strlen(p)); //6printf("%d\n", strlen(p + 1)); //5printf("%d\n", strlen(*p)); //errprintf("%d\n", strlen(p[0])); //errprintf("%d\n", strlen(&p)); //随机值printf("%d\n", strlen(&p + 1));//随机值printf("%d\n", strlen(&p[0] + 1)); //5printf("%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 )
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]));
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// = intreturn 0;
}
新人博主,如果有地方解释的不对或者不清晰,麻烦大佬们海涵,如果可以麻烦从评论区指出,我一定会加以修改,万分感谢
最后麻烦大佬们动一下发财的小手一键三连,千万分感谢