防御性编程技巧

C语言与CPP编程 2022-02-13 10:01

击上方“C语言与CPP编程”,选择“关注/置顶/星标公众号

干货福利,第一时间送达!


在防御性编程的大框架之下,有许多常识性的规则。人们在想到防御性编程的时候,通常都会想到“断言”,这没有错。我们将在后面对此进行讨论。但是,还是有一些简单的编程习惯可以极大地提高代码的安全性。
尽管看上去像是常识,但是这些规则却往往被人们忽视,这就是为什么世界上并不缺少低质量软件的原因。只要程序员们警惕起来,受到足够的督促,更高的安全性和可靠的开发很容易就能够实现。
在下面的几页中,将列出防御性编程的一些规则。我们将先从粗略的概览开始,整体地描述防御的技巧、过程和步骤。随着讨论的深入,我们会加入更多的细节,进一步地逐条分析每条代码语句。在这些防御性技巧中,有一些是与具体的编程语言相关的。这很自然——如果你的编程语言会让你射伤到自己的脚,那么你一定要穿上防弹靴。
在阅读这些规则时,请对你自己进行一个评估。在这些规则中,现在你遵循的有几条?你打算采纳哪些规则?

1 使用好的编码风格和合理的设计哪

我们可以通过采用良好的编程风格,来防范大多数编码错误。这与本篇的其他章节自然地吻合。很多简单的事,如选用有意义的变量名,或者审慎地使用括号,都可以使编码变得更加清晰明了,并减少缺陷出现的可能性。
同样地,在投入到编码工作中之前,先考虑大体的设计方案,这也非常关键。“最好的计算机程序的文本是结构清晰的。”(见参考书目Kernighan Plaugher 78)从实现一套清晰的API、一个逻辑系统结构以及一些定义良好的组件角色与责任开始入手,将使你避免以后处处头疼的局面。

2 不要仓促地编写代码

闪电式的编程太常见了。使用这种编程方式的程序员会很快地开发出一个函数,马上把这个函数交给编译器来检查语法,接着运行一遍看看能不能用,然后就进入下一个任务。这种方式充满了危险。
相反,在写每一行时都三思而后行。可能会出现什么样的错误?你是否已经考虑了所有可能出现的逻辑分支?放慢速度,有条不紊的编程虽然看上去很平凡,但这的确是减少缺陷的好办法。
关键概念 欲速则不达。每敲一个字,都要想清楚你要输入的是什么。
在C语言中,有一个会使追求速度的程序员犯错的陷阱,即将“==”错误地输入为“=”。前者为相等关系测试,而后者则是变量赋值。如果你的编译器功能不全(或者关闭了警告功能),你就不会得到相关提示,也就无从得知自己输入了不该输入的东西。
一定要在完成与一个代码段相关的所有任务之后,再进入下一个环节。例如,如果你决定先编写主体部分,再加入错误检查和处理,那么一定要确保这两项工作的完成都遵循章法。如果你要推迟错误检查的编写,而直接开始编写超过三个代码
段的主体部分,你一定要慎之又慎。你也许真的想随后再回来编写错误检查,但却一而再再而三地向后推迟,这期间你可能会忘记很多上下文,使得接下来的工作更加耗时和琐碎。(当然,到时候你还要面临一些人为设置的最后截止日期。)
遵循章法是一种习惯,需要牢记于心并切实贯彻。如果你不立即做正确的事,那么将来你很可能也不会再去做正确的事。现在就行动,不要等到撒哈拉沙漠下雨了才行动。晚做不如早做,因为将来再做将需要遵循更多的章法。

3 不要相信任何人

妈妈曾告诉过你,不要和陌生人说话。不幸的是,要想开发一个好的软件,就需要更加愤世嫉俗,对人的天性更加不信任。即便是没有恶意的代码用户,也可能会给你的程序带来麻烦。防御意味着不能相信任何人。
下面这些情况可能是给你带来麻烦的原因:
— 真正的用户 意外地提供了假的输入,或者错误地操作了程序;
— 恶意的用户 故意造成不好的程序行为;
— 客户端代码 使用错误的参数调用了你的函数,或者提供了不一致的输入;
— 运行环境 没有为程序提供足够的服务;
— 外部程序库 运行失误,不遵从你所依赖的接口协议。
你甚至可能会在编写一个函数时犯下愚蠢的错误,或者错误地使用三年前编写的代码,因为你忘记了这些代码究竟是怎样运行的。不要设想所有的一切都运行良好,或者所有的代码都会正确地运行。在你的程序各处都添加安全检查。时刻注意弱点,用更多的防御性代码防止弱点的出现。
关键概念 不要相信任何人毫无疑问,任何人(包括你自己)都可能把缺陷引入你的程序逻辑当中。用怀疑的眼光审视所有的输入和所有的结果,直到你能证明它们是正确的时为止。

4 编码的目标是清晰,而不是简洁

如果要你从简洁(但是有可能让人困惑)的代码和清晰(但是有可能比较冗长)的代码中选择,一定要选那些看上去和预期相符合的代码,即使它不太优雅。例如,将复杂的代数运算拆分为一系列单独的语句,使逻辑更清晰。
想一想,谁会是你的代码的读者。这些代码也许需要一位初级程序员来进行维护,如果他不能理解代码的逻辑,那么他肯定会犯一些错误。复杂的结构或不常用的语言技巧可以证明你在运算符优先级方面渊博的知识,但是这些实际上会扼杀代码的可维护性。请保持代码简单。
不能维护的代码是不安全的。举一个极端的例子,过于复杂的表达式会使编译器生成错误的代码,许多编译器优化的错误就是因此而造成的。
关键概念 简单就是一种美。不要让你的代码过于复杂。

5 不要让任何人做他们不该做的修补工作

内部的事情就应该留在内部。私人的东西就应该用锁和钥匙保管起来。不要把你的代码初稿示于众人。不管你多么礼貌地恳求,只要你稍不注意,别人就会篡改你的数据,然后自以为是地试着调用“仅用于执行”的例行程序。不要让他们这样做。
— 在面向对象的语言中,通过将属性设为专用(private)来防止对内部类数据的访问。在C++中,可以考虑使用Cheshire cat/pimpl idiom。(见参考书目Meyers 97)
— 在过程语言中,你仍然可以使用面向对象(oo)的打包概念,将private数据打包在不透明的类型背后,并提供可以操作它们的定义良好的公共函数。
— 将所有变量保持在尽可能小的范围内。不到万不得已,不要声明全局变量。如果变量可以声明为函数内的局部变量,就不要在文件范围上声明。如果变量可以声明为循环体内的局部变量,就不要在函数范围上声明。
说说“何时”
何时进行防御性编程?你是否在事情不顺利时才开始这样做?或者在整理一些你不理解的代码时才开始?
不,这是不对的,你应该从始到终地使用这些防御性编程的技巧。它们应该成为你的第二天性。成熟的程序员已经从经验中得到教训,在吃过不止一遍的苦头之后,他们才明白了增加预防措施是明智的。
在开始编写代码时就应用防御性策略,比改进代码时才应用要容易得多。如果你很晚才试着将这些策略强加进去,就不可能做到万无一失。如果你在问题出现后才开始添加防御性代码,实际上你是在调试,被动地做出反应,而不是积极地防患于未然。
然而,在调试的过程中,甚至在添加新的功能时,你将发现一些你希望验证的情况。这常常是添加防御性代码的好时机。

6 编译时打开所有警告开关

大多数语言的编译器都会在你“伤了它们感情的时候”给出一大堆错误信息。当这些编译器碰到潜在的有缺陷代码时(如在赋值之前使用C或C++变量)[3],它们也会给出各种各样的警告。通常情况下,这些警告可以有选择地启用或禁用。
如果你的代码中充满了危险的构造,你将会得到数页的警告信息。糟糕的是,通常的反应是禁用编译器的警告功能,或者干脆不理会这些信息。这两种做法都不可取。
在任何情况下都要打开你的编译器的警告功能。如果你的代码产生了任何的警告信息,立即修正代码,让编译器的报错声停下来。在启用了警告功能之后,不要对不能安静地完成编译的代码感到满意。警告的出现总是有原因的。即使你认为某个警告无关紧要,也不要置之不理。否则,总有一天这个警告会隐藏一个确实重要的警告。
关键概念 编译器的警告可以捕捉到许多愚蠢的编码错误。在任何情况下都启用它们。确保你的代码可以安安静静地完成编译。

7 使用静态分析工具

编辑器警告是对代码的一次有限的静态分析(即在程序运行之前执行的代码检查)的结果。
还有许多独立的静态分析工具可供使用,如用于C语言的lint(以及更多新出的衍生工具)和用于.NET汇编程序的FxCop。你的日常编程工作,应该包括使用这些工具来检查你的代码。它们会比你的编译器挑出更多的错误。

8 使用安全的数据结构

如果你做不到,那么就安全地使用危险的数据结构。
最常见的安全隐患大概是由缓冲溢出引起的。缓冲溢出是由于不正确地使用固定大小的数据结构而造成的。如果你的代码在没有检查一个缓冲的大小之前就写入这个缓冲,那么写入的内容总是有可能会超过缓冲的末尾的。
这种情况很容易出现,如下面这一小段C语言代码所示:
char *unsafe_copy(const char *source){char *buffer = new char[10];strcpy(buffer, source);return buffer;}
如果source中数据的长度超过10个字符,它的副本就会超出buffer所保留内存的末尾。随后,任何事都可能会发生。数据出错是最好情况下的结果——一些其他数据结构的内容会被覆盖。而在最坏的情况下,恶意用户会利用这个简单的错误,把可执行代码加入到程序堆栈中,并使用它来任意运行他自己的程序,从而劫持了计算机。这类缺陷常常被系统黑客所利用,后果极其严重。
避免由于这些隐患而受到攻击其实很简单:不要编写这样的糟糕代码!使用更安全的、不允许破坏程序的数据结构——使用类似C++的string类的托管缓冲。或者
对不安全的数据类型系统地使用安全的操作。通过把strcpy更换为有大小限制的字符串复制操作strncpy,就可以使上面的C代码段得到保护。
char *safer_copy(const char *source){    char *buffer = new char[10];    strncpy(buffer, source, 10);    return buffer;}


9 检查所有的返回值

如果一个函数返回一个值,它这样做肯定是有理由的。检查这个返回值。如果返回值是一个错误代码,你就必须辨别这个代码并处理所有的错误。不要让错误悄无声息地侵入你的程序;忍受错误会导致不可预知的行为。
这既适用于用户自定义的函数,也适用于标准库函数。你会发现:大多数难以察觉的错误都是因为程序员没有检查返回值而出现的。不要忘记,某些函数会通过不同的机制(例如,标准C库的errno)返回错误。不论何时,都要在适当的级别上捕获和处理相应的异常。

10 审慎地处理内存(和其他宝贵的资源)

对于在执行期间所获取的任何资源,必须彻底释放。内存是这类资源最常提到的一个例子,但并不是唯一的一个。文件和线程锁也是我们必须小心使用的宝贵资源。做一个好的“管家”。
不要因为觉得操作系统会在你的程序退出时清除程序,就不注意关闭文件或释放内存。对于你的代码还会执行多长时间,是否会耗尽所有的文件句柄或占用所有的内存,其实你一无所知。你甚至不能肯定操作系统是否会完全释放你的资源,有的操作系统就不是这样的。
有一个学派说:“在确定你的程序可以运行之前,不要担心内存的释放;只有在能够确定之后再添加所有相关的释放操作。”这种观点大错特错,是一种荒谬而且危险的做法。它会使你在使用内存时出现许许多多的错误;你将不可避免地在某些地方忘记释放内存。
关键概念 重视所有稀有的资源。审慎地管理它们的获取和释放。
Java和.NET使用垃圾回收器来执行这些繁重的清洁工作,所以你可以“忘记”释放资源。让它们进入工作状态,这样在运行时将会不时地进行清扫。这真是一种享受,不过,不要因此而对安全性抱有错误的想法。你仍然需要思考。你必须显式地终止对那些不再需要,或不会被自动清除的对象的引用;不要意外地保留对对象的引用。不太先进的垃圾回收器也很容易会被循环引用蒙蔽(例如,A引用B,B又引用A,除此之外没有对A和B的引用)。这会导致对象永远不会被清除;这是一种难以发现的内存泄漏形式。

11 在声明位置初始化所有变量

这是一个显而易见的问题。如果你初始化了每个变量,它们的用途就会是明确的。依靠像“如果我不初始化它,我就不关心初始值”的经验主义是不安全的。代码将会发展。未初始化的值以后可能随时都会变成问题。
C和C++使这个问题更加复杂化。如果你意外地使用了一个没有初始化的变量,那么你的程序在每次运行的时候都将得到不同的结果,这取决于当时内存中的垃圾信息是什么。在一个地方声明一个变量,随后再对它进行赋值,在这之后再使用它,这样会为错误打开一个窗口。如果赋值的语句被跳过,你就会花费大量的时间来寻找程序随机出现各种行为的原因。在声明每个变量的时候就对它进行初始化,就可以把这个窗口关上,因为即使初始化时赋的值是错误的,至少出现的错误行为也是可以预知的。
比较安全的语言(如Java和C#)通过为所有变量定义初始值,回避了这个易犯的错误。在声明变量的时候对它进行初始化仍然是一种好的做法,这样可以提高代码的明确性。

12 尽可能推迟一些声明变量

尽可能推迟一些声明变量,可以使变量的声明位置与使用它的位置尽量接近,从而防止它干扰代码的其他部分。这样做也使得使用变量的代码更加清晰。你不再需要到处寻找变量的类型和初始化,在附近声明使这些都变得非常明显。
不要在多个地方重用同一个临时变量,即使每次使用都是在逻辑上相互分离的区域中进行的。变量重用会使以后对代码重新完善的工作变得异常复杂。每次都创建一个新的变量——编译器会解决任何有关效率的问题。

13 使用标准语言工具

在这方面,C和C++都是一场噩梦。它们的规范有许多不同的版本,使得许多情况成为了其他实现的未定义行为。现如今有很多种编译器,每个编译器都有一些与其他编译器稍有不同的行为。这些编译器大部分是相互兼容的,但是仍然存在大量的绳索会套住你的脖子。
明确地定义你正在使用的是哪个语言版本。除非你的项目要求你(最好是有一个好的理由),否则不要将命运交给编译器,或者对该语言的任何非标准的扩展。如果该语言的某个领域还没有定义,就不要依赖你所使用的特定编译器的行为(例如,不要依赖你的C编译器将char作为有符号的值对待,因为其他的编译器并不是这样的)。这样做会产生非常脆弱的代码。当你更新了编译器之后,会发生什么?一位新的程序员加入到开发团队中,如果他不理解那些扩展,会发生什么?依赖于特定编译器的个别行为,将导致以后难以发现的错误。

14 使用好的诊断信息日志工具

当你编写新的代码时,常常会加入很多诊断信息,以确定程序的运行情况。在调试结束后是否应该删除这些诊断信息呢?保留这些信息对以后再次访问代码会带来很多方便,特别是如果在此期间可以有选择地禁用这些信息。
有很多诊断信息日志系统可以帮助实现这种功能。这些系统中很多都可以使诊断信息在不需要的时候不带来任何开销;可以有选择地使它们不参加编译。

15 审慎地进行强制转换

大多数语言都允许你将数据从一种类型强制转换(或转换)为另一种类型。这种操作有时比其他操作更成功。如果试着将一个64位的整数转换为较小的8位数据类型,那么其他的56位会怎么样呢?你的执行环境可能会突然抛出异常,或者悄悄地使你数据的完整性降级。很多程序员并不考虑这类事情,所以他们的程序就会表现出不正常的行为。
如果你真的想使用强制转换,就必须对之深思熟虑。你所告诉编译器的是:“忘记类型检查吧:我知道这个变量是什么,而你并不知道。”你在类型系统中撕开了一个大洞,并直接穿越过去。这样做很不可靠。如果你犯了任何一种错误,编译器将只会静静地坐在那里小声嘀咕道:“我告诉过你的。”如果你很幸运(例如使用Java或C#),运行时可能会抛出异常以让你了解发生了错误,但这完全依赖于你要进行的是什么转换。
C和C++对于数据类型的精度并不明确,所以对于数据类型的可互换性不要做任何假设。不要假设int和long的大小相同并且可以相互赋值,即使你在你的平台上侥幸可以这样做。代码可以在平台之间移植,但是糟糕的代码可移植性很差。

16 细则

低级别防御性代码的编写技巧有很多。这些技巧是日常编程工作的组成部分,包含在对现实世界的一种健康的怀疑当中。下面的几条细则值得考虑:
提供默认的行为
大多数语言都提供了一条switch语句;这些语言都将碰到default case的执行情况。如果default case是错误的,在代码中将错误情况明示出来。如果一切都正常,也要在代码中明示顺利执行的情况,只有这样维护代码的程序员才会理解程序的执行情况。
同样地,如果你要编写一条不带else子句的if语句,停下来想一想,你是否应该处理这个逻辑上的默认情况。
遵从语言习惯
这条简单的建议将确保你的读者可以明白你所编写的所有代码。他们做出的错误设想会更少。
检查数值的上下限
即使是最基本的计算,也会使数值型变量上溢或下溢。对此要非常注意。语言规范或核心库提供了一些机制,用来确定各个标准类型的大小——别忘了使用这些机制。确保你了解所有可用的数值类型,以及每种类型最适合的情况。
检查并确保每一次运算都是可靠稳定的。例如,确保自己一定不要使用可能会造成除0错误的值。
正确设置常量
C或C++语言的程序员真的应该对常量的设置保持高度警惕,这会让日子好过很多。尽可能将所有可以设置成常量的都设为常量。这样做有两个好处:首先,常量的限制条件可以充当代码记录;其次,常量使编译器可以找到你所犯下的愚蠢错误。这样,你就可以避免修改超出上下限的数据了。

转载:https://blog.csdn.net/everpenny/article/details/6316698

C语言与CPP编程 C语言/C++开发,C语言/C++基础知识,C语言/C++学习路线,C语言/C++进阶,数据结构;算法;python;计算机基础等
评论
  • PLC组态方式主要有三种,每种都有其独特的特点和适用场景。下面来简单说说: 1. 硬件组态   定义:硬件组态指的是选择适合的PLC型号、I/O模块、通信模块等硬件组件,并按照实际需求进行连接和配置。    灵活性:这种方式允许用户根据项目需求自由搭配硬件组件,具有较高的灵活性。    成本:可能需要额外的硬件购买成本,适用于对系统性能和扩展性有较高要求的场合。 2. 软件组态   定义:软件组态主要是通过PLC
    丙丁先生 2025-01-06 09:23 85浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 145浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 173浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 68浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 87浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 119浏览
  •     为控制片内设备并且查询其工作状态,MCU内部总是有一组特殊功能寄存器(SFR,Special Function Register)。    使用Eclipse环境调试MCU程序时,可以利用 Peripheral Registers Viewer来查看SFR。这个小工具是怎样知道某个型号的MCU有怎样的寄存器定义呢?它使用一种描述性的文本文件——SVD文件。这个文件存储在下面红色字体的路径下。    例:南京沁恒  &n
    电子知识打边炉 2025-01-04 20:04 100浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 45浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 104浏览
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 80浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 75浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 127浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦