(嵌入式八股)第1章 C语言(三)
1.21 sizeof与strlen的区别
虽然 sizeof
和 strlen
都可以用于计算某些类型的数据的“长度”,但它们的本质、用途和适用场景有所不同。以下是它们的主要区别:
本质区别
sizeof()
:是一个运算符,在编译时就能够得到结果。它用于计算指定数据类型或变量所占用的内存字节数。strlen()
:是一个函数,在运行时被调用。它用于计算以'\0'
(空字符)结尾的字符串的字符个数(不包括'\0'
)。
用途区别
- sizeof():计算变量、类型或数据结构所占用的内存空间(字节数)。适用于所有数据类型,包括基本类型(如 int、char 等)、数组、指针、结构体等。注意:sizeof 计算的是类型大小,并不是值的大小。对于数组来说,sizeof 可以返回整个数组占用的内存大小。
- strlen():计算以 '\0' 结尾的字符串的长度,即字符串中实际字符的个数,不包括字符串的结束符 '\0'。只能用于以 '\0' 结尾的字符串(即 C 风格的字符串)。在运行时计算字符串的长度,因此需要遍历整个字符串直到遇到 '\0'。
适用范围区别
- sizeof():可以用于任何数据类型,包括基本数据类型、指针、数组、结构体等。对于静态数组,它可以直接计算数组的大小(即整个数组占用的内存空间)。
- strlen():只能用于C风格字符串(以 '\0' 结尾的字符数组)。计算的是字符串的字符数,并不考虑数组的总大小或内存分配。
包含结束符('\0')的区别
- sizeof():计算数组或类型的大小时会包含 '\0' 结尾字符,尤其是对于字符数组。例如,sizeof("hello") 返回 6(5 个字符 + 1 个结束符)。
- strlen():计算字符串的长度时不包含 '\0' 结束符,它只返回字符串中的实际字符数。例如,strlen("hello") 返回 5。
示例对比
使用 sizeof():
因为数组大小为 5 个字符 + 1 个 '\0' 字符
使用 strlen():
因为只计算字符数,不包括 '\0'
总结对比
1.22 常见的变量定义
• int a;:声明了一个名为 a
的变量,类型为 int
,即它存储一个整数值。
• int *a;:声明了一个名为 a
的变量,它是一个指针,指向 int
类型的变量。即 a
存储的是一个 int
类型变量的地址。
• int **a;:声明了一个名为 a
的变量,它是一个指针,指向一个 int
类型指针。即 a
存储的是另一个指向 int
类型数据的指针的地址。
• int a[10];:声明了一个名为 a
的数组,它有 10 个元素,每个元素是 int
类型。数组大小在编译时就已经确定。
• int *a[10];:声明了一个名为 a
的数组,它有 10 个元素,每个元素是 int
类型的指针。即,a
存储的是 10 个指向 int
类型数据的指针。
• int (*a)[10];:声明了一个名为 a
的指针,它指向一个数组,该数组包含 10 个 int
类型的元素。即,a
存储的是一个数组的地址,数组大小为 10,且每个元素为 int
类型。
• int (*a)(int);:声明了一个名为 a
的指针,它指向一个函数,该函数接受一个 int
类型参数并返回一个 int
类型的结果。即,a
是一个函数指针,指向返回值为 int
且接受一个 int
类型参数的函数。
• int (*a[10])(int);:声明了一个名为 a
的数组,它包含 10 个元素,每个元素是一个指向函数的指针。这个函数接受一个 int
类型的参数,并返回 int
类型的值。即,a
是一个数组,每个元素都是一个指向返回 int
并接受一个 int
参数的函数的指针。
- 指针:用于存储其他变量的内存地址。
- 数组:用于存储多个同类型的数据元素。
- 函数指针:指向具有特定签名的函数,允许动态调用函数。
- 复杂声明:理解变量声明的顺序和括号的优先级非常重要。
int *a[10]
是一个指向int
类型的指针数组,而int (*a)[10]
是一个指向数组的指针,数组中有 10 个int
类型的元素。
1.23 数组名与指针的区别
数组名和指针看起来有一些相似,但它们在地址、大小、改变性和运算等方面还是存在区别。
地址
- 数组名:数组名本身是一个常量指针,指向数组的首元素。它并不是一个普通的指针变量,因此不能改变它的值(不能让数组名指向其他位置)。取数组名的地址,得到的是数组名所指元素的地址,即数组首元素的地址。
- 指针:指针是一个变量,存储一个内存地址。指针变量可以指向任意类型的对象。取指针的地址,得到的是指针变量自身的地址,而不是它所指向的内容的地址。
大小
- 数组名:数组名的大小是固定的,等于整个数组所占用的内存大小。例如,一个包含 n 个元素的数组 arr,它的大小是 n * sizeof(element),即整个数组的大小。
- 指针:指针的大小是固定的,大小等于指针类型所占用的内存空间。对于大多数平台,指针的大小通常是 4 或 8 字节,具体取决于系统的架构(32 位或 64 位)。
改变性
- 数组名:数组名是一个常量指针,不能改变。它始终指向数组的首元素,不能被重新赋值以指向其他位置。
- 指针:指针是一个变量,可以改变其值,即指向不同的内存位置。指针可以被重新赋值指向其他对象或内存位置。
运算
- 数组名:数组名不能进行指针运算,也就是说,数组名是一个常量,不能修改它指向的元素。尽管数组名看起来像指针,实际上它并不支持指针运算。
- 指针:指针支持指针运算,包括加法、减法、递增、递减等。指针运算是通过改变指针的值来进行内存访问的。指针运算可以移动指针,使其指向不同的内存地址。
总结
1.24 简述C++有几种传值方式之间的区别
值传递(pass by value)
参数以值的方式传递给函数,函数内部对参数的修改不会影响到原始数据。函数会创建参数的副本,在函数的作用域内使用副本进行操作。常用于传递简单类型的参数。
引用传递(pass by reference)
参数以引用的方式传递给函数,函数内部对参数的修改会影响到原始数据。函数直接操作原始数据,没有创建副本。可以用于传递任意复杂类型的参数,比如对象或容器。
指针传递(pass by pointer)
参数以指针的方式传递给函数,函数内部可以通过指针来访问和修改原始数据。函数通过指针间接操作原始数据,需要注意空指针和指针的解引用。可以用于传递需要动态分配内存的参数,或者需要返回多个值的情况。
1.25 数组指针与指针数组的区别
数组指针(Pointer to an Array)
定义:
p
是一个指针,指向一个整型的一维数组,数组长度为 n
。p
不是一个数组,而是一个指向数组的指针。剩余60%内容,订阅专栏后可继续查看/也可单篇购买
作者简介:仅用几个月时间0基础天坑急转嵌入式开发,逆袭成功拿下华为、vivo、小米等15个offer,面试经验100+,收藏20+面经,分享求职历程与学习心得。 专栏内容:这是一份覆盖嵌入式求职过程中99%问题指南,详细讲解了嵌入式开发的学习路径、项目经验分享、简历优化技巧、面试心得及实习经验,从技术面,HR面,AI面,主管面,谈薪一站式服务,助你突破技术瓶颈、打破信息差,争取更多大厂offer。