【发布时间】:2013-04-26 22:15:13
【问题描述】:
使用Arduino Ethernet Server Library,有什么区别:
server.write(data);,
server.print(data);,和
server.println(data);
我知道printIn 添加了一个新行,而print 没有。我找不到server.write(); 的任何示例。
【问题讨论】:
使用Arduino Ethernet Server Library,有什么区别:
server.write(data);,
server.print(data);,和
server.println(data);
我知道printIn 添加了一个新行,而print 没有。我找不到server.write(); 的任何示例。
【问题讨论】:
(长答案,如果不方便,请跳至底部的 TL;DR)
print() 和 write() 来自哪里要找出答案,我们可以查看源代码。 Server 是在arduino/libraries/Ethernet/EthernetServer.h 中定义的EthernetServer 类的一个实例(仅限选定的行)
#include "Server.h"
class EthernetClient;
class EthernetServer :
public Server {
private:
public:
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
using Print::write;
};
好的,所以它是Server。 Server 定义在 /usr/share/arduino/hardware/arduino/cores/arduino/Server.h 中,而且内容很少:
class Server : public Print {
public:
virtual void begin() =0;
};
这意味着 server 是Print 的子类,因此我们可以在那里查找write() 和print() 之间的差异。
print() 和 write() 参数我们看到这个类(即Print)定义了许多重载的print()方法:
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
和三个重载的write() 方法:
virtual size_t write(uint8_t) = 0;
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
virtual size_t write(const uint8_t *buffer, size_t size);
如你所见C字符串write使用块write(第三种方法),而在默认实现中,块写入使用字节写入(第一种方法),这是纯虚方法:virtual size_t write(uint8_t) = 0;。它必须在派生自Print 的每个类中被覆盖。此外,write() 块也可以被覆盖,以便更有效地写入多字节数据。
所以,参数方面:
write():关于字节 (uint8_t)、字节缓冲区和字符数组指针(= 常规 C 字符串)print():Arduino Strings、ints 和 longs(在任何基础上)、floats,以及从 Printable 派生的任何类,除了 chars 和 C 字符串。
如您所见,在形式上,参数write() 和print() 之间几乎没有重叠。例如,只有write() 采用uint8_t,但只有print() 可以采用char。唯一重叠的区域是 C 风格的字符串:有 print(const char[]); 和 write(const char *str);。然而,即使在像char 这样的情况下,print() 函数也会简单地调用write(uint8_t):
size_t Print::print(char c)
{
return write(c);
}
print(char[]) 也是如此
write() 在 `EthernetServerEthernetServer 类引入了块写入方法
size_t EthernetServer::write(const uint8_t *buffer, size_t size)
在EthernetServer 中,write(uint8_t) 只是简单地向块写入:
size_t EthernetServer::write(uint8_t b)
{
return write(&b, 1);
}
由于所有print() 调用和非uint8_t write() 调用都使用write(uint8_t) 或write(uint8_t*, size_t),因此在EthernetServer 类中,每个print/write 调用都是使用块进行的写。
print() 和write() 之间进行选择
thunking print() 函数(例如 print(char c))很可能会被 gcc 编译器内联,但如果您担心这一点,您可以调用 write() 而不是 print()。
您可能想要调用write() 而不是print() 以节省几个时钟周期的一种情况是您持有byte/uint8_t 并且您需要打印那个。使用print(),您的数据需要转换为 4 字节值 (int),然后使用更多代码打印。在这种情况下,write() 会快一点。
另一方面,代码一致性可能也很有价值。从这个角度来看,进行所有print() 调用可能是有意义的。
然而,大多数时候,您的类型将决定调用 print() 函数:write 只能接受三种类型的输入。
TL;DR:那么您的问题的答案是print() 和write() 之间没有太大区别,除了:
write() 方法(字节或块)是在任何情况下执行在某处发送字符的实际工作的方法。write() 可以接受字节(uint8_t)、字节缓冲区和字符数组指针(= 常规 C 字符串)作为参数,而 print() 接受 Arduino Strings、ints 和 longs(在无论基数)、floats,以及从Printable 派生的任何类,以及chars 和C 字符串。所以我们可能会说write() 的级别低于print(),因为它只接受低级别的类型。write() 打印byte/uint8_t 类型,但print 无处不在让你的代码看起来好一点恕我直言(主要是因为它不会提高print() 与write()问题)。【讨论】:
write()?如果你已经在使用它支持的变量类型会更快吗?