【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)3

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)

【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)2:https://developer.aliyun.com/article/1474745


💮 💮 💮 strlen计算字符串数组

int main()
{
  char arr[] = "abcdef";

  printf("%zd\n", strlen(arr));//arr也是数组首元素的地址 6
  printf("%zd\n", strlen(arr + 0));//arr + 0是数组首元素的地址,6
  //printf("%zd\n", strlen(*arr));//?传递是'a'-97,//err
  //printf("%zd\n", strlen(arr[1]));//?'b'-98//err
  printf("%zd\n", strlen(&arr));//6, &arr虽然是数组的地址,但是也是指向数组的起始位置
  printf("%zd\n", strlen(&arr + 1));//随机值
  printf("%zd\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 - 5

  return 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的参数必须是字符串的起始地址,才能正确计算长度。

  • arrarr+0都是数组首元素的地址,传给strlen计算长度都是6
  • *arrarr[1]访问到的是字符'a''b',传给strlen会报错
  • &arr虽然是数组的地址,但也指向数组第一个元素,所以strlen(&arr)可以正确计算长度
  • &arr+1会指向字符串的其他位置,传给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;
}
  1. printf(“%zd\n”, sizeof§);//4/8
    pchar*类型的指针变量,存放的是a的地址,是地址,那就是4或8字节。
    2.printf(“%zd\n”, sizeof(p + 1));4/8

p+1计算的是'b'字符的地址,依然是地址,大小也是4/8个字节。

printf(“%zd\n”, sizeof(*p));// 1字节

p访问的是'a'字符,sizeof计算的是字符类型大小,是1字节。

printf(“%zd\n”, sizeof(p[0]));//1字节

p[0]等价于*(p+0),(p+0)也等价pp[0]-- > *(p+0) - >*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个字节

  1. 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,因为p+1指向从'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))随机值;

同理,&p+1找的是p后面地址,然后开始在p后面不断找\0,也是随机值。

  1. printf(“%zd\n”, strlen(&p[0] + 1));//5
    因为&p[0]+1指向从'b'开始的字符串。

strlen只能计算字符串常量或以'\0'结束的字符串长度,其他情况如字符,地址都无法识别长度,可能导致随机值或报错。

3️⃣ 总结

本小节我们学习了sizeof和strlen对一维字符数组,字符串数组和指针变量进行练习,我们应该对指针有了更多的理解,但是他们都离不开我们以下的知识点。sizeof用于计算变量或类型占用的内存空间(以字节为单位),它是编译期就能确定的常量。

strlen用于计算字符串长度,但仅限于以'\0'作为字符串结束标志的字符串。它需要在运行期扫描字符串计算长度,他接收地址,不能接收数值,否则就会访问编译器就会报错,造成访问冲突。

【C指针】深入理解指针(最终篇)数组&&指针&&指针运算题解析(一)3

相关文章
|
4月前
|
JavaScript
js 解析 byte数组 成字符串
js 解析 byte数组 成字符串
102 5
|
22天前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
58 0
|
3月前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
|
3月前
|
存储 Java 开发者
【编程基础知识】 计算机中的数学魔法:二进制加减运算全解析
本文深入解析了计算机中二进制加减运算的原理,涵盖原码、反码和补码的概念及应用,结合具体示例,帮助读者理解计算机底层数学运算机制,适合Java开发者学习。
71 0
|
3月前
|
人工智能
魔法指针 之 指针变量的意义 指针运算
魔法指针 之 指针变量的意义 指针运算
28 0
|
3月前
|
Serverless 编译器 C语言
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
|
5月前
|
存储 JavaScript 前端开发
一文带你深度解析:JavaScript中对象与数组的威力究竟有多大?
一文带你深度解析:JavaScript中对象与数组的威力究竟有多大?
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
93 2
|
15天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

推荐镜像

更多
下一篇
开通oss服务