广州网站建设哪个平台好,深圳市网站建设外包公司排名,织梦模板建站,互联网直播营销大赛主题#x1f308;write in front :#x1f50d;个人主页 #xff1a; 啊森要自信的主页 ✏️真正相信奇迹的家伙#xff0c;本身和奇迹一样了不起啊#xff01; 欢迎大家关注#x1f50d;点赞#x1f44d;收藏⭐️留言#x1f4dd;希望看完我的文章对你有小小的帮助write in front :个人主页 啊森要自信的主页 ✏️真正相信奇迹的家伙本身和奇迹一样了不起啊 欢迎大家关注点赞收藏⭐️留言希望看完我的文章对你有小小的帮助如有错误可以指出让我们一起探讨学习交流一起加油鸭。 文章目录 前言1️⃣ sizeof和strlen的对⽐➡️sizeof➡️ ➡️ strlen➡️ ➡️ ➡️sizeof 和 strlen的对⽐ 2️⃣ 数组和指针笔试题解析 ⼀维数组字符数组 sizeof计算字符数组strlen计算字符数组 字符串数组 sizeof计算字符串数组 strlen计算字符串数组 指针变量 sizeof计算指针变量strlen计算指针变量 3️⃣ 总结 前言
通过前几节我们学了前面五节指针和学习了sizeof操作符知识本小节阿森继续和你一起做一维数组和指针笔试题当然还有关于指针运算的笔试题干货满满让我们开始做题 当然宝子们天气变化大记得多注意保暖 1️⃣ sizeof和strlen的对⽐
➡️sizeof
C语言中sizeof不是一个函数而是一个编译期计算类型大小的内置操作符所以它没有函数原型。 sizeof没有函数原型它的语法形式是
sizeof(类型名)
或
sizeof 变量名类型名需要括号变量名可以不需要括号。直接写类型名后面会报错。 sizeof 只关注占⽤内存空间的⼤⼩不在乎内存中存放什么数据。
int main()
{int a 66;printf(%zd\n, sizeof(a));//4printf(%zd\n, sizeof(int));//4printf(%zd\n, sizeof a);//这里可以省略括号printf(%zd\n, sizeof int);//err类型名本身不能直接跟在sizeof后面如sizeof int是错误的return 0;
}当然sizeof也可以求数组的大小 数组名就是数组⾸元素(第⼀个元素)的地址。 sizeof(数组名)----sizeof中单独放数组名这⾥的数组名表⽰整个数组计算的是整个数组的⼤⼩单位是字节. 数组名(如a)这⾥的数组名表⽰整个数组取出的是整个数组的地址整个数组的地址和数组⾸元素 的地址是有区别的 除此之外任何地⽅使⽤数组名数组名都表⽰⾸元素的地址。 int main()
{int arr1[4] { 0 };char arr2[4] { 0 };printf(%zd\n, sizeof(arr1));//16 //单独放数组名这⾥的数组名表⽰整个数组计算的是整个数组的⼤⼩printf(%zd\n, sizeof(int [4]));//16 //int占用4个字节int[4]数组占用4 * 4 16字节printf(%zd\n, sizeof(arr2));//4 //单独放数组名这⾥的数组名表⽰整个数组计算的是整个数组的⼤⼩printf(%zd\n, sizeof(char [4]));//4 //arr2是char类型的数组char占1字节char[4]数组占用4 * 1 4字节。return 0;
}➡️ ➡️ strlen
strlen 是C语⾔库函数功能是求字符串⻓度。函数原型如下 size_t strlen ( const char * str );统计的是从 strlen 函数的参数 str 中这个地址开始向后 \0 之前字符串中字符的个数。 strlen 函数会⼀直向后找 \0 字符直到找到为⽌所以可能存在越界查找。 int main()
{char arr1[20] abcdef;size_t len strlen(arr1);//不包含结尾\0,所以长度是6。printf(len %zd\n, len);size_t sz sizeof(arr1);//arr1这个数组变量占用的内存大小即20字节。printf(sz %zd\n, sz);char arr2[] { a, b,c };printf(%zd\n, strlen(arr2));//随机值因为找不到\0char arr3[6] abcdef;//err//因为abcdef包含7个字符及结尾\0,大于arr3的空间6字节会导致越界。return 0;
}➡️ ➡️ ➡️sizeof 和 strlen的对⽐ 2️⃣ 数组和指针笔试题解析 ⼀维数组 数组名就是数组⾸元素(第⼀个元素)的地址。 sizeof(数组名)----sizeof中单独放数组名这⾥的数组名表⽰整个数组计算的是整个数组的⼤⼩单位是字节. 数组名(如a)这⾥的数组名表⽰整个数组取出的是整个数组的地址整个数组的地址和数组⾸元素 的地址是有区别的 除此之外任何地⽅使⽤数组名数组名都表⽰⾸元素的地址。 char* arr1[10]; //存放字符指针的指针数组
int* arr2[10]; //存放整型指针的指针数组
int(*arr3[5])[6] ;//存放数组指针的数组指针数组
int(*arr4[5])(int);//存放函数指针的函数指针数组int main()
{int a[] { 6,7,8,9,10 };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));
}细解
printf(“%d\n”, sizeof(arr));//20 sizeof中单独放数组名这⾥的数组名表⽰整个数组计算的是整个数组的⼤⼩单位是字节.printf(“%zd\n”, sizeof(a 0));4/8 a没有单独放在sizeof内部也没有取地址因此a表示的就是数组首元素的地址,a0还是首元素的地址 是地址那么大小就是 4/8地址大小只与环境有关32位是4个字节64位就是8个字节printf(“%zd\n”, sizeof(*a)); //4 a表示的就是数组首元素的地址,*a 就是首元素首元素是6,6的类型是int,大小就是4个字节printf(“%zd\n”, sizeof(a 1));//4/8 a表示的就是数组首元素的地址a1就是第二个元素的地址这里的计算的是第二个元素的地址的大小,地址大小只与环境有关32位是4个字节64位就是8个字节4/8printf(“%zd\n”, sizeof(a[1]));//4 a[1]是数组的第二个元素(7)大小是4个字节printf(“%zd\n”, sizeof(a));//4/8 a - 取出的是数组的地址但是数组的地址也是地址是地址大小就是4/8个字节printf(“%zd\n”, sizeof(*a));//20 两种方法1. 和 * 抵消 2.a 的类型是数组指针int(*)[5]*a就是对数组指针解引用访问一个数组的大小是20个字节printf(“%zd\n”, sizeof(a 1));//4/8 a1是跳过整个数组后的一个地址是地址大小就是4/8个字节printf(“%zd\n”, sizeof(a[0]));//4/8 a[0]是数组第一个元素的地址是地址大小就是4/8个字节printf(“%zd\n”, sizeof(a[0] 1));//4/8 a[0] 1 是第二个元素的地址大小就是4/8个字节 字符数组 sizeof计算字符数组
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;
}
细解
printf(“%d\n”, sizeof(arr)); //6 sizeof中单独放数组名这⾥的数组名表⽰整个数组计算的是整个数组的⼤⼩单位是字节.6个字节printf(“%d\n”, sizeof(arr 0));// 4/8 arr0 是数组第一个元素的地址是地址大小就是4/8个字节 printf(“%d\n”, sizeof(* arr));// 1* *arr是首元素计算的是首元素的大小字符a的类型是char,是1个字节printf(“%d\n”, sizeof(arr[1]));// 1 arr[1] 是第二个元素字符b类型是char是1个字节printf(“%d\n”, sizeof(arr));//4/8 arr取得是整个数组的地址是地址大小就是4/8个字节。printf(“%d\n”, sizeof(arr 1));//4/8 arr取得是整个数组的地址arr1跳过整个数组跳过了6个数组的元素指向f后面也是地址大小就是4/8个字节。 strlen计算字符数组
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”, strlen(arr));//随机值 arr为数组名也就是数组首元素的地址但是字符数组中没有\0,strlen将会继续查找\0但是\0是不知道在什么位置出现所以无法计算为随机值。printf(“%d\n”, strlen(arr 0));//随机值 arr0也是数组首元素的地址但是字符数组中没有\0,strlen将会继续查找\0但是\0是不知道在什么位置出现所以无法计算为随机值。并且与前面的随机值一样printf(“%d\n”, strlen(*arr));//非法访问 //a-97//printf(%d\n, strlen(*arr));//err// //b-98//printf(%d\n, strlen(arr[1]));//err注意 *arr取出来的是字符a,字符a对应的ASCII码值为97而97为内存空间里的一个地址 size_t strlen ( const char * str );内存空间这块97地址传给strlen,strlen能直接访问这块不属于他的空间吗 答案是不可以因为它不属于strlen的作用域一旦访问了就成非法访问了。当然arr[1]也是如此 printf(“%d\n”, strlen(arr[1]));//非法访问 注意 *arr1[1]取出来的是字符b,字符a对应的ASCII码值为98而98为内存空间里的一个地址 size_t strlen ( const char * str );内存空间这块97地址传给strlen,strlen能直接访问这块不属于他的空间吗 答案是不可以因为它不属于strlen的作用域一旦访问了就成非法访问了,编译器就会报错–访问冲突。 printf(“%d\n”, strlen(arr));//随机值 arr虽然是数组的地址但是也是指向数组的起始位置那就是从数组首元素开始找嘛没有\0,找不到那就是随机值了 printf(“%zd\n”, strlen(arr 1));//随机值-6 arr1跳过整个数组也就是跳过6个char类型的元素从f后面的地址开始查找\0因此相比从头开始找少了6个元素 printf(“%d\n”, strlen(arr[0] 1));//随机值-1 a[0] 1 是第二个元素的地址比随机值少一个元素a 字符串数组 sizeof计算字符串数组
int main()
{char arr[] abcdef;printf(%zd\n, sizeof(arr));printf(%zd\n, sizeof(arr 0));printf(%zd\n, sizeof(*arr));printf(%zd\n, sizeof(arr[1]));printf(%zd\n, sizeof(arr));printf(%zd\n, sizeof(arr 1));printf(%zd\n, sizeof(arr[0] 1));return 0;
}解析char arr[] “abcdef\0”//字符串别忘记有\0,也占用一个char空间
printf(“%zd\n”, sizeof(arr));//7 数组名arr单独放计算的是整个数组的大小7个字节printf(“%zd\n”, sizeof(arr 0));//4/8 arr0是数组首元素的地址地址的大小是4/8个字节printf(“%zd\n”, sizeof(*arr));//1 *arr是数组的首元素这里计算的是首元素(a)的大小 ,类型为char,大小为1printf(“%zd\n”, sizeof(arr[1]));//1 *arr是数组的首元素这里计算的是第二个元素(b)的大小 ,大小为1printf(“%zd\n”, sizeof(arr));//4/8 arr - 是数组的地址数组的地址也是地址是地址就是4/8个字节printf(“%zd\n”, sizeof(arr 1));//4/8 arr1跳过整个数组指向了数组的后边4/8printf(“%zd\n”, sizeof(arr[0] 1));//4/8 arr[0] 1是第二个元素的地址 是地址那就是4/8/kbd 小结 sizeof计算变量或类型的大小单位是字节(byte)。%zd格式说明符用于打印size_t类型的值这也是sizeof的返回类型。字符串常量abcdef实际上是一个char数组最后一个元素是\0。所以sizeof(arr)算出的是整个字符串占用的空间包含结束符即7个字节。当sizeof操作数是数组时它计算的是整个数组占用的字节数。当操作数是指针时它计算的是指针变量本身占用的字节数与它指向的对象大小无关。 strlen计算字符串数组
int main()
{char arr[] abcdef;printf(%zd\n, strlen(arr));//arr也是数组首元素的地址 6printf(%zd\n, strlen(arr 0));//arr 0是数组首元素的地址6//printf(%zd\n, strlen(*arr));//传递是a-97,//err//printf(%zd\n, strlen(arr[1]));//?b-98//errprintf(%zd\n, strlen(arr));//6, arr虽然是数组的地址但是也是指向数组的起始位置printf(%zd\n, strlen(arr 1));//随机值printf(%zd\n, strlen(arr[0] 1));//arr[0] 1是第二个元素的地址 - 5return 0;
}printf(“%zd\n”, strlen(arr));// 6 arr也是数组首元素的地址从a地址开始直到\0停止并且\0不计算在内。 printf(“%zd\n”, strlen(arr 0));//6 arr 0是数组首元素的地址也是从a地址开始直到\0停止并且\0不计算在内。 printf(“%zd\n”, strlen(*arr));//访问冲突 *arr传递是a-97,字符a对应的ASCII码值为97而97为内存空间里的一个地址不属于数组arr的空间那么就会访问冲突 printf(“%zd\n”, strlen(arr[1]));//访问冲突 注意 同样在字符串中该结论同样适用arr[1],因为arr[1]取出来的是字符b,字符b的ASCII码值98同样是一个地址但不是字符串起始地址。 传递*arr或arr[1]给strlen,strlen是无法直接访问这些地址处的内存空间的因为这些地址都不属于strlen的作用域。 而arr名本身以及arr地址arr,都是字符串的起始地址所以可以作为strlen函数的参数。 小结 strlen的参数必须是字符串的起始地址才能正确计算长度。 arr和arr0都是数组首元素的地址传给strlen计算长度都是6*arr和arr[1]访问到的是字符a和b,传给strlen会报错arr虽然是数组的地址但也指向数组第一个元素所以strlen(arr)可以正确计算长度arr1会指向字符串的其他位置传给strlen会产生随机值或者错误结果 指针变量 sizeof计算指针变量
int main()
{char* p abcdef;printf(%zd\n, sizeof(p));printf(%zd\n, sizeof(p 1));printf(%zd\n, sizeof(*p));printf(%zd\n, sizeof(p[0]));printf(%zd\n, sizeof(p));printf(%zd\n, sizeof(p 1));printf(%zd\n, sizeof(p[0] 1));return 0;
}printf(“%zd\n”, sizeof§);//4/8 p是char*类型的指针变量存放的是a的地址是地址那就是4或8字节。 printf(“%zd\n”, sizeof(p 1));4/8 p1计算的是b字符的地址依然是地址大小也是4/8个字节。 printf(“%zd\n”, sizeof(*p));// 1字节 p访问的是a字符sizeof计算的是字符类型大小是1字节。 printf(“%zd\n”, sizeof(p[0]));//1字节 p[0]等价于*(p0),(p0)也等价pp[0]-- *(p0) - *p也是访问a字符是1字节。 printf(“%zd\n”, sizeof(p));//4/8 p是p指针变量的地址是地址大小也是4/8个字节。 printf(“%zd\n”, sizeof(p 1));//4/8个字节 p 1是指向p指针变量后面的空间也是地址是4/8个字节 printf(“%zd\n”, sizeof(p[0] 1));//4/8 p[0]1访问b字符的地址是地址就是4/8个字节。 小结 sizeof运算符计算 指针变量时计算的是指针变量本身占用的内存空间4或8字节。字符或整数类型时计算的是该类型变量占用的内存大小如char是1字节。地址时地址也是指针类型计算的还是指针类型占用的内存大小4或8字节。 strlen计算指针变量
int main()
{char* p abcdef;printf(%zd\n, strlen(p));printf(%zd\n, strlen(p 1));//printf(%zd\n, strlen(*p));//printf(%zd\n, strlen(p[0]));printf(%zd\n, strlen(p));printf(%zd\n, strlen(p 1));printf(%zd\n, strlen(p[0] 1));return 0;
}运行该代码打印strlen的结果解释 printf(“%zd\n”, strlen(p ));//6 因为p指向字符串abcdef的首地址,strlen计算字符串长度就是6。 printf(“%zd\n”, strlen(p 1));//5 结果是5,因为p1指向从b开始的字符串长度是5。 printf(“%zd\n”, strlen(*p));//访问冲突 *p是a字符 size_t strlen ( const char * str );strlen接受一个地址‘a’字符不是地址如果是的话那又是访问ASCII码值然后报错。 printf(“%zd\n”, strlen(p[0])); //访问冲突 同理p[0]也是字符不能用strlen。 printf(“%zd\n”, strlen(p));随机值 p是指针p的地址strlen无法识别结果是随机值。 printf(“%zd\n”, strlen(p 1))随机值; 同理p1找的是p后面地址然后开始在p后面不断找\0,也是随机值。 printf(“%zd\n”, strlen(p[0] 1));//5 因为p[0]1指向从b开始的字符串。 strlen只能计算字符串常量或以\0结束的字符串长度其他情况如字符地址都无法识别长度可能导致随机值或报错。 3️⃣ 总结
本小节我们学习了sizeof和strlen对一维字符数组字符串数组和指针变量进行练习我们应该对指针有了更多的理解但是他们都离不开我们以下的知识点。sizeof用于计算变量或类型占用的内存空间(以字节为单位)它是编译期就能确定的常量。 strlen用于计算字符串长度但仅限于以\0作为字符串结束标志的字符串。它需要在运行期扫描字符串计算长度他接收地址不能接收数值否则就会访问编译器就会报错造成访问冲突。 数组名就是数组⾸元素(第⼀个元素)的地址。 sizeof(数组名)----sizeof中单独放数组名这⾥的数组名表⽰整个数组计算的是整个数组的⼤⼩单位是字节. 数组名(如a)这⾥的数组名表⽰整个数组取出的是整个数组的地址整个数组的地址和数组⾸元素 的地址是有区别的 除此之外任何地⽅使⽤数组名数组名都表⽰⾸元素的地址。 如果你看到这里让我们把掌声送给我们自己 感谢你的收看如果文章有错误可以指出我不胜感激让我们一起学习交流如果文章可以给你一个小小帮助可以给博主点一个小小的赞