为什么全局对象构造函数在 Arduino 中只打印前 2 个字符?
Why does global object constructor print only the first 2 chars in Arduino?
我创建了一个名为 Fred 的 class,这里是 .h 和 .cpp 文件:
Fred.h
#ifndef Fred_h
#define Fred_h
#include "Arduino.h"
class Fred
{
public:
Fred();
};
#endif
Fred.cpp
#include "Fred.h"
Fred::Fred()
{
Serial.begin(115200);
Serial.println("Hello Arduino!");
}
在草图中,我刚刚全局初始化了 class 对象:
#include <Fred.h>
Fred a;
void setup()
{}
void loop()
{}
它应该打印 Hello Arduino!在串行终端中,但它只打印前两个字节 "He",这很奇怪!我读过有关 SIOF(静态初始化顺序 Fiasco)的文章,这可能是问题所在,但如果是这样,为什么它打印 2 个字节而不是未在 all.If 处打印 我在设置函数中声明了它正常工作的对象。
首先,由于 SIOF,尝试在另一个单例的构造函数中调用单例的方法是错误的。在对象可能尚未构造时调用该对象的方法是不好的,并且可能导致奇怪的行为。所以,如果通过在 Serial 和 Fred 上避免 SIOF 问题消失了,你不需要质疑为什么它打印 2 个字节。
编辑:
如何避免 SIOF?有很多方法可以做到这一点。但是如果你想为 Fred 保留一个单例,你应该使用 COFU (https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Construct_On_First_Use)
为了避免 SIOF,你可以这样做:
我创建了一个名为 Fred 的 class,这里是 .h 和 .cpp 文件:
Fred.h
#ifndef Fred_h
#define Fred_h
#include "Arduino.h"
class Fred
{
public:
Fred();
void printMessage();
};
#endif
Fred.cpp
#include "Fred.h"
Fred::Fred()
{
// nothing to do here
}
void Fred::printMessage()
{
Serial.println("Hello Arduino!");
}
草图中:
#include <Fred.h>
Fred a;
void setup()
{
Serial.begin(9600);
}
void loop()
{
a.printMessage();
}
希望这对您有所帮助。
您无法从静态对象的构造函数访问 Serial
,因为无法保证 Serial
会被设置。在输入 main
.
之前,您不想执行任何 "real work"
arduino的串口实现大概只有两个字符的硬件缓冲。一旦发送了前两个,剩下的就被扔掉了,因为对它们进行排队和安排中断服务的必要逻辑可能还没有设置。
所以第一个字符立即开始发送。第二个字符位于等待第一个字符完成的硬件缓冲区中。剩余的字符应该被传送到中断处理程序(这样每次缓冲区为空,因为前一个字符已经完全发送,一个新的字符可以开始被发送出去),但显然还没有设置。
我创建了一个名为 Fred 的 class,这里是 .h 和 .cpp 文件:
Fred.h
#ifndef Fred_h
#define Fred_h
#include "Arduino.h"
class Fred
{
public:
Fred();
};
#endif
Fred.cpp
#include "Fred.h"
Fred::Fred()
{
Serial.begin(115200);
Serial.println("Hello Arduino!");
}
在草图中,我刚刚全局初始化了 class 对象:
#include <Fred.h>
Fred a;
void setup()
{}
void loop()
{}
它应该打印 Hello Arduino!在串行终端中,但它只打印前两个字节 "He",这很奇怪!我读过有关 SIOF(静态初始化顺序 Fiasco)的文章,这可能是问题所在,但如果是这样,为什么它打印 2 个字节而不是未在 all.If 处打印 我在设置函数中声明了它正常工作的对象。
首先,由于 SIOF,尝试在另一个单例的构造函数中调用单例的方法是错误的。在对象可能尚未构造时调用该对象的方法是不好的,并且可能导致奇怪的行为。所以,如果通过在 Serial 和 Fred 上避免 SIOF 问题消失了,你不需要质疑为什么它打印 2 个字节。
编辑: 如何避免 SIOF?有很多方法可以做到这一点。但是如果你想为 Fred 保留一个单例,你应该使用 COFU (https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Construct_On_First_Use)
为了避免 SIOF,你可以这样做:
我创建了一个名为 Fred 的 class,这里是 .h 和 .cpp 文件:
Fred.h
#ifndef Fred_h
#define Fred_h
#include "Arduino.h"
class Fred
{
public:
Fred();
void printMessage();
};
#endif
Fred.cpp
#include "Fred.h"
Fred::Fred()
{
// nothing to do here
}
void Fred::printMessage()
{
Serial.println("Hello Arduino!");
}
草图中:
#include <Fred.h>
Fred a;
void setup()
{
Serial.begin(9600);
}
void loop()
{
a.printMessage();
}
希望这对您有所帮助。
您无法从静态对象的构造函数访问 Serial
,因为无法保证 Serial
会被设置。在输入 main
.
arduino的串口实现大概只有两个字符的硬件缓冲。一旦发送了前两个,剩下的就被扔掉了,因为对它们进行排队和安排中断服务的必要逻辑可能还没有设置。
所以第一个字符立即开始发送。第二个字符位于等待第一个字符完成的硬件缓冲区中。剩余的字符应该被传送到中断处理程序(这样每次缓冲区为空,因为前一个字符已经完全发送,一个新的字符可以开始被发送出去),但显然还没有设置。