我来自使用VB.NET进行.NET编程,这是我针对基于Arduino的应用程序进行的第一个C开发。
仔细阅读Arduino头文件(寻找类似.ToString
的__FlashStringHelper
方法的东西)时,我偶然发现了下一个#define
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
首先我了解:
这是一个带有名为
string_literal
的参数的宏,该参数在括号内的表达式中以某种方式使用。就这样!这些
<
,>
标志和*
指针突然之间是什么?
最佳答案
常规类型转换
在C++中,可以使用多种类型的类型转换在类型之间进行转换。它们很重要,因为C++是强类型语言,并且编译器不一定知道类型之间的任何给定转换都是安全或明智的。默认情况下,除非您明确告诉它要做什么,否则它将发出错误或警告。
所有C++强制类型转换都具有以下格式:
x_cast <new_type> (expression)
x_cast
可以是以下之一:static_cast
,dynamic_cast
,reinterpret_cast
或const_cast
。当您要强制编译器在不相关的指针类型之间进行转换时,将使用重新解释转换。结果是一个指向内存中完全相同的数据的指针。但是,它将被当作不同的类型来处理(或解释),这可以允许进行一些有趣的操作。
例如,假设您有一个指向4字节无符号整数的指针,并且想单独访问每个字节。您可以通过将指针重新解释为1字节类型来做到这一点,如下所示:
uint32_t num = 12345;
uint32_t *p1 = #
uint8_t *p2 = reinterpret_cast<uint8_t*>(p1);
// Access the individual bytes:
uint8_t byte0 = p2[0];
uint8_t byte1 = p2[1];
uint8_t byte2 = p2[2];
uint8_t byte3 = p2[3];
指针
p1
和p2
都指向num
变量中存储的数据。不同之处在于,通过p2
访问它会导致编译器将其视为1字节无符号整数(而不是原始的4字节类型)。这使您可以提取/操作原始变量内不同位置的单个字节。对于这样的简单示例,
reinterpret_cast
是相当安全的。但是,在许多情况下,如果使用不当,它可能会犯非常严重的错误,或者根本无用。一个示例将尝试将float
指针重新解释为int
。就其本身而言,它不会做任何坏事。但是,结果将是完全无用的,因为如果您尝试像float
一样处理int
,则底层的二进制表示形式没有意义。对于对象,也可以使用相同的方法,使您可以将一个类的实例解释为另一个类的实例。但是,它不会进行任何智能转换。它只是强制以不同的方式处理原始二进制数据,这意味着您必须非常确信重新解释是有意义的。
Arduino
完全扩展后,您在Arduino文件中标识的行相当复杂,因此我们将对其进行分解。正如我认为您已经确定的那样,它定义了一个名为
F()
的宏,并且该宏采用了一个名为string_literal
的参数。顾名思义,它打算与字符串文字
F("like this")
一起使用。在表面之下,编译器将字符串文字视为指向字符数组的指针;或换句话说,char *
。在
F()
宏内部,字符串文字被放入另一个名为PSTR()
的宏中。这基本上增加了很多其他内容,这些内容告诉编译器将字符串数据存储在程序空间(草图位于Arduino上)而不是SRAM(变量位于其中)中。此时,
reinterpret_cast
开始起作用。 PSTR()
中的所有内容都很重要,但是它并不会真正影响 Actor 表看到的数据类型。您基本上可以想象它的行为如下:char *ptr = "my string data";
reinterpret_cast<const __FlashStringHelper *>(ptr);
__FlashStringHelper
是一个类,这意味着它的类型与char *
无关。这就是为什么我们需要重新解释它的原因,因此编译器知道我们对操作的安全性负责。使用强制转换的结果时,它将像指向__FlashStringHelper
对象的指针一样工作,这意味着可以使用其方法访问/处理字符串数据。实际上,实际上没有创建
__FlashStringHelper
的实例。基础数据仍然只是我们的字符串文字。这是C++有趣的方面之一-您可以实际上调用不存在的对象的方法,只要该对象不尝试访问不存在的成员数据即可。
关于c++ - 了解神秘的C++语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22708300/