Используя библиотеку Ethernet-сервера Arduino, в чем разница между:
server.write(data);
, server.print(data);
и server.println(data);
Я знаю, что printIn
добавляет новую строку, а print
— нет. Я не могу найти примеры для server.write();
.
Используя библиотеку Ethernet-сервера Arduino, в чем разница между:
server.write(data);
, server.print(data);
и server.println(data);
Я знаю, что printIn
добавляет новую строку, а print
— нет. Я не могу найти примеры для server.write();
.
(Длинный ответ, перейдите к TL;DR внизу, если он громоздкий)
print()
и write()
Чтобы узнать, мы можем посмотреть на источник. Server
является экземпляром класса EthernetServer
, определенного в arduino/libraries/Ethernet/EthernetServer.h
(только выбранные строки)
#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;
};
Это означает, что сервер является подклассом 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 String
s, int
s и long
s (в любой базе), float
s и любой класс, производный от 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()
в `EthernetServerКласс EthernetServer
представляет метод блочной записи.
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()
и не-55_ вызовы 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()
: запись может принимать только три типа ввода.
TL;DR: Ответ на ваш вопрос заключается в том, что между print()
и write()
нет большой разницы, за исключением:
write()
(байтовые или блочные) — это методы, которые выполняют фактическую работу по отправке символов куда-либо в любом случае.write()
может принимать байты (uint8_t
), байтовые буферы и указатели массива символов (= обычные строки C) в качестве параметров, тогда как print()
принимает Arduino String
s, int
s и long
s (в любой базе), float
s и любой класс, производный от Printable
, кроме того до chars
и до струн. Таким образом, мы можем сказать, что write()
имеет более низкий уровень, чем print()
, учитывая тот факт, что он принимает только низкоуровневые типы.write()
для печати типов byte
/uint8_t
, но print
везде делает ваш код немного лучше, ИМХО (в основном потому, что он не вызывает вопросов print()
по сравнению с write()
).write()
? Это быстрее, если вы уже используете тип переменной, который он поддерживает?
- person Anonymous Penguin; 27.04.2013