1

Arduinoイーサネットサーバーライブラリを使用すると、次の違いは何ですか:

server.write(data);server.print(data);、および server.println(data);

printInが新しい行を追加することを知っていますが、そうではありprintません。の例が見つかりませんserver.write();

4

1 に答える 1

4

(長い回答、TLにスキップしてください;扱いにくい場合は下部のDR)

どこprint()からwrite()来たのか

調べるために、ソースを見ることができます。 で定義されServerたクラスのインスタンスです(選択された行のみ)EthernetServerarduino/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;
};

わかりましたServerServerは で定義されて/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&);

および 3 つのオーバーロードされた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(3 番目の方法) を使用し、デフォルトの実装では、ブロック書き込みはバイト書き込み (最初の方法) を使用します。これは純粋な仮想方法ですvirtual size_t write(uint8_t) = 0;。から派生するすべてのクラスでオーバーライドする必要がありますPrintwrite()さらに、マルチバイトデータをより効率的に書き込むために、ブロックをオーバーライドすることもできます。

したがって、パラメータごとに:

  • write(): バイト ( uint8_t)、バイト バッファ、および char 配列ポインタ (= 通常の C 文字列)
  • print(): Arduino Strings、intおよびlongs (任意のベース)、 、および C 文字列に加えて、floatから派生した任意のクラス。Printablechars

ご覧のとおり、正式には、パラメーターwrite()print()テイクの間にはほとんど重複がありません。たとえば、 のみwrite()を取りますが、取ることができるのはuint8_tだけです。重複する唯一の領域は C スタイルの文字列です: と があります。ただし、関数が単に呼び出すような場合でも、次のようになります。print()charprint(const char[]);write(const char *str);charprint()write(uint8_t)

size_t Print::print(char c)
{
  return write(c);
}

同じことが当てはまりますprint(char[])

write()`イーサネットサーバーで

ブロック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()呼び出しと非uint8_t write()呼び出しは or のいずれwrite(uint8_t)かを使用するためwrite(uint8_t*, size_t)EthernetServerクラスではすべてのprint/write呼び出しはブロック書き込みを使用して行われます。

パフォーマンスと と のprint()選択write()

サンクprint()関数 ( などprint(char c)) は、gcc コンパイラによってインライン化される可能性が最も高いですが、これが心配な場合は、write()の代わりに呼び出すことができますprint()

数クロック サイクルを節約する代わりに呼び出したい場合の 1 つは、 /を保持していて、それを出力する必要がある場合ですデータを使用するには、4 バイト値 ( ) に変換してから、さらにコードを使用して出力する必要があります。この場合、少し速くなります。write()print()byteuint8_tprint()intwrite()

一方で、コードの一貫性もおそらく価値があります。この観点から、すべてのprint()呼び出しを行うことは理にかなっています。

ただし、ほとんどの場合、型によって関数の呼び出しが決まりprint()ます。 write は 3 種類の入力しか受け付けません。


TL;DRprint() : あなたの質問に対する答えは、とwrite()を除いて大きな違いはないということです:

  • write()メソッド (バイトまたはブロック) は、あらゆる場合に文字をどこかに送信する実際の作業を行うメソッドです。
  • write()バイト ( uint8_t)、バイト バッファー、および char 配列ポインター (= 通常の C 文字列) をパラメーターとして受け取ることができますが、C 文字列に加えて、print()ArduinoStringの s、ints およびlongs (任意のベース)、floats、および から派生した任意のクラスを受け取ります。 . 低レベルの型しかとらないという事実を考えると、は よりも低レベルであると言えます。Printablecharswrite()print()
  • ほとんどの場合、出力タイプによって、どちらを使用するかが決まります。最速のコードwrite()を印刷byte/uint8_tタイプに使用しprintますが、どこでもコードの見栄えを良くします(主にprint()対のwrite()質問が発生しないため)。
于 2013-04-27T05:06:25.453 に答える