1

私はArduino#defineをプログラミングしており、関数に渡されるバイト配列を設定するためにステートメントを使用したいと考えていEthernet.begin()ます。現時点では、次のコードを使用しており、すべてが期待どおりに機能します。

#define MAC_ARRAY { 0x43, 0xA3, 0xDA, 0x0D, 0xF5, 0xA5 }

void setup() {
  byte mac[] = MAC_ARRAY;

  if (Ethernet.begin(mac) == 0) {
    ...
  }
}

上記のコードでわかるように、値byte mac[] = MAC_ARRAY;を使用するたびに、ソース コード全体で宣言する必要がありMAC_ARRAYます。ただし、それを述べることは避けたいと思います(変数がインスタンス化されるため、「長い道のりで」メモリの問題が発生する可能性があるとも思います)、何らかの形で適切なものを関数に直接mac[]渡します。MAC_ARRAYEthernet.begin()

出来ますか?その場合、どのように#define MAC_ARRAY ...ステートメントを変更すればよいですか?

4

1 に答える 1

0

joachim Pilborg が既に述べたように、C++11 互換のコンパイラがあれば、リテラル配列を関数に渡すことができ、関数 (Ethernet.begin) にはbegin(std::initializer_list)バリアントがあります。

ただし、あなたの例は解決策に近いです。mac グローバル(可能な場合はconst ) を作成し、定義を削除します。

uint8_t const mac[] = { 0x43, 0xA3, 0xDA, 0x0D, 0xF5, 0xA5 };
   //^^^^^ -> if begin isn't able to handle const, remove the const here.

void setup() {
  if (Ethernet.begin(mac) == 0) {
    ...
  }
}

これにより、mac が 1 回だけ起動され、再利用されます (メモリの問題はありません)。

コードによっては、いくつかの可能性があります。

  1. Ethernet.beginパラメータとして参照/ポインタで定義されます。これは、通常は 6 バイト (sizeof(mac)) より小さい参照のみを渡していることを意味します。そしてmacはメモリに一度だけ保存されます。

  2. ここで mac をconstと宣言する必要があります。そのため、コンパイラはそれを最適化し、値をマシン命令のオペコードに直接組み込むことができます。したがって、最適化フラグをオンにしてコンパイルする必要があります。ここを参照

  3. 両方が当てはまらない場合でも、mac は 1 回インスタンス化され、スタック メモリを介して値 (コピー) で渡されるため、問題ありません。

最適なのは ...byte const macbegin(byte const*)の両方であるため、コンパイラはメモリと時間を節約するための最善の方法を決定します。


グローバルにするデメリットはありません。define は変換されたオペコードになります。また、最適化された場合、グローバルな const も (上記のケース 2 を参照) なります。ただし、const は 1 つのインスタンス、1 つのオペコーダ (Mac の初期化中) になり、残りはこのインスタンスへの参照/エイリアス (値のアドレス指定) になります。動作は、の実装によって定義されますEthernet

于 2013-10-02T10:46:25.253 に答える