const int、enum、または#defineがはるかに理にかなっているときにピンにint変数を使用する理由


24

コードの実行中にピンが変更される可能性が低いのに、なぜ人々が変数を使用してピン番号を指定するのですか?

多くのint場合、ピン定義に使用されていることがわかりますが、

int led = 13;

使用するとき const int

const int led = 13;

またはenum、または#define

#define LED 13

はるかに理にかなっています。

Arduinoサイトのチュートリアル(たとえば、ほとんどの人が実行する最初のチュートリアルBlink)にもあります。

それconst intが好まれるどこか読ん#define。なぜ最初から人々が悪い習慣を身につけることを許すのではなく、これが最初から奨励されていないのですか?しばらく前に気づきましたが、最近私をいらいらさせ始めました。

メモリ/賢明なコンピューティングです/処理const intenumまたはそのことについては#define、より良い平野よりint、すなわちに格納し、少ないメモリを占有する異なるメモリ(フラッシュ、EEPROM、SRAM)、実行速度が速く、迅速にコンパイルするには?


これはの複製のように見えるかもしれませんが、定数に#defineまたはconst intを使用する方が良いでしょうか?しかし、私は人々が変数を使用する理由と、どのタイプの定数が優れているかではなく、変数を使用しない場合のパフォーマンスをどのように改善するかという問題に取り組んでいます。


9
ひどいものがひどくなるからです。ほとんどの愛好家は経験豊富なプログラマーではないため、他の愛好家に悪い習慣を教えます。
イグナシオバスケス-エイブラムス

1
具体的には、ピンと、digitalWriteなどの基本的なArduinoのAPI関数の単純な形は、適切な組み込み設計、すなわち使用してマスクやポート全体のための単一のメモリアドレス奨励していません
crasic

回答:


20
const int led = 13;

それが正しい方法です。あるいは:

const byte led = 13;

ピンはいくつありますか?

一部のチュートリアルでは、品質管理が十分ではありませんでした。

const byteに比べて、を使用した方がパフォーマンスは向上しますintが、コンパイラは何をしているのかを認識できるほどスマートです。

あなたができることは、あなた自身のコードでそれらを使用することにより、人々がより効率的なテクニックを使うように優しく奨励することです。


コメントへの回答

  1. コメンターがあることを示唆しているbyteC.これが正しい標準ではありませんが、これはArduinoのStackExchangeサイトです、と私はArduinoのIDEによって供給される標準タイプを使用することが許容されると考えています。

    Arduino.hには次の行があります。

    typedef uint8_t byte;

    これはとまったく同じではないことに注意してくださいunsigned charuint8_t vs unsigned charおよびuint8_t≠unsigned charを参照してください

  2. 別のコメンターは、バイトを使用してもパフォーマンスが必ずしも向上しないことを示唆しています。これよりも小さい数値intは昇格するためですint(これについては、整数昇格規則を参照してください)。

    ただし、const識別子のコンテキストでは、コンパイラはどのような場合でも効率的なコードを生成します。たとえば、「点滅」を分解すると、元の形式でこれが得られます。

    00000086 <loop>:
      86:   8d e0           ldi r24, 0x0D   ; 13
      88:   61 e0           ldi r22, 0x01   ; 1
      8a:   1b d1           rcall   .+566       ; 0x2c2 <digitalWrite>

    実際、次のいずれの場合でも同じコードが生成されます13

    • リテラルです
    • #define
    • const int
    • const byte

コンパイラは、いつ1つのレジスタに数値を収めることができ、いつできないかを認識します。しかし、良い練習それはあなたを示しコーディングを使用する意図を。それは作るconstことは番号が変更されないことが明らかになり、それを作ることはbyte(またはuint8_t)、それはあなたが少数を期待していることが明らかになります。


紛らわしいエラーメッセージ

避けるべきもう1つの主な理由#defineは、間違えた場合に表示されるエラーメッセージです。エラーがあるこの「点滅」スケッチを考えてみましょう。

#define LED = 13;

void setup() {
  pinMode(LED, OUTPUT);      // <---- line with error
}

void loop() {
  digitalWrite(LED, HIGH);   // <---- line with error 
  delay(1000);             
  digitalWrite(LED, LOW);    // <---- line with error
  delay(1000);              
}

表面上はOKに見えますが、次のエラーメッセージが生成されます。

Blink.ino: In function ‘void setup()’:
Blink:4: error: expected primary-expression before ‘=’ token
Blink:4: error: expected primary-expression before ‘,’ token
Blink:4: error: expected `;' before ‘)’ token
Blink.ino: In function ‘void loop()’:
Blink:8: error: expected primary-expression before ‘=’ token
Blink:8: error: expected primary-expression before ‘,’ token
Blink:8: error: expected `;' before ‘)’ token
Blink:10: error: expected primary-expression before ‘=’ token
Blink:10: error: expected primary-expression before ‘,’ token
Blink:10: error: expected `;' before ‘)’ token

最初に強調表示された行(行4)を見ると、「=」記号さえ表示されいません。さらに、線は正常に見えます。ここで問題が何であるかはかなり明らかです(= 13に置き換えられていますLED)が、行がコードのさらに400行下にある場合、問題がLEDの定義方法にあることは明らかではありません。

私はこれまで何度も(自分自身を含む)人が落ちるのを見てきました。


ピンはいくつありますか?ニックは非常に良いポイントです。ほとんどのボードは数百ではなく数十(つまり255以上)の範囲にあるため、int過剰です...つまり、Arduinoが最終的にTeraボードで登場するまで... :-)
Greenonline

2
Cにはbyte型がありません。という意味unsigned charです。
ケビン

ほとんどのコンテキストでは、に昇格するよりも小さい型の整数値があるため、必ずしものbyte代わりにパフォーマンスが向上するとは限りません。intintint
ピートベッカー

1
C doesn't have a byte type. You mean unsigned char.-私の答えはArduinoのコンテキストで、これにはtypedef uint8_t byte;。したがって、Arduinoの場合、使用byteは問題ありません。
ニックギャモン

Performance won't necessarily be better with byte instead of int-修正された投稿を参照してください。
ニックギャモン

19

イグナシオが正しく述べているように、それは基本的に彼らがよく知らないからです。そして、彼らは彼らを教えた人々(または彼らが学習時に使用したリソース)がよりよく知らなかったので、よりよく知りません。

Arduinoのコードとチュートリアルの多くは、プログラミングのトレーニングを受けたことのない人によって書かれており、プログラミングの適切なトレーニングを受けずに自分で非常に教えられている人がリソースから非常に「独学」しています。

私がその場所で見かけるチュートリアルコードのスニペットの多く(特にYouTubeビデオでのみ利用可能なもの---すぐに)は、試験で採点した場合、失敗マークになります。

はい、a constは非constよりも優先され、aよりも優先され#defineます:

  • A const#define非constとは異なり、aなど)はRAMを割り当てません
  • A const(非constが、とは異なりのように#define値を明示的に与える)タイプ

2番目のポイントは特に興味深いものです。具体的には埋め込み型鋳造(とそうでない言っていない限り(long)3)またはタイプサフィックス(3L)または小数点(の存在3.0)、#define数は常に整数であろうと、それがあたかもその値に対して実行されたすべての数学なり整数。問題ありませんが、あなたがしようとすると、興味深いシナリオに実行することができますほとんどの時間#define整数を格納することができますよりも大きい値、など#define COUNT 70000して、他との数学的操作を行うintことで値。を使用するconstことにより、コンパイラに「この値はこの変数タイプとして扱われる」ことを伝えることができます-そのため、代わりに:const long count = 70000;を使用し、すべてが期待どおりに動作します。

また、場所の周りに値を渡すときに型をチェックするというノックオン効果もあります。const longを予期する関数にを渡してみてください。int変数の範囲を狭めることについて文句を言うでしょう(またはシナリオによってはコンパイルに完全に失敗することさえあります)。でそれを行う#defineと、それは単にあなたに間違った結果を与え続け、何時間もあなたの頭を傷つけてしまいます。


7
コンテキストによってconst変数 RAMを必要とする場合あることに注意してください。たとえば、constexpr以外の関数からの戻り値を使用して変数を初期化する場合などです。
ピーターブルームフィールド

同様に、const int foo = 13; bar(&foo);コンパイラが実際のメモリを割り当てる必要があることは間違いありませんfoo
イルマリカロネン

3
収まらない値に展開するマクロを定義するとint、コンパイラは値が収まる最小の型を持つものとして扱います(符号付きと符号なしに関するモジュロ規則)。あなたがシステムを使っている場合はint16ビットである、#define count 70000になりますcountように見えるlong、それは次のように定義されていたかのように、const long count = 70000;。さらに、これらのバージョンのいずれかをcount関数expect intに渡すと、正常なコンパイラーはそれらを同じものとして扱います。
ピートベッカー

1
私は@PeteBeckerに同意します-のような構造#define COUNT 70000はintに切り捨てられませんが、コンパイラはそれをその数を保持するのに十分な大きさの型として扱います。あなたCOUNTがそれがintではないことを使用するときそれが明白でないかもしれないことは本当ですが、const longとにかく同じことを言うことができます。
ニックギャモン

2
「#defineは常に整数です」それは正しくありません。整数リテラルの規則を採用し、それらをプリプロセッサマクロに適用しています。リンゴとポップミュージックを比較するようなものです。COUNTあなたの例の式は、コンパイルの前に式で置き換えられます。式は、70000リテラルの規則によって定義されたタイプを持つ2か、13Lまたは4.0リテラルの規則によって定義されます。#defineこれらの式のエイリアスに使用するという事実は無関係です。#define必要に応じて、Cコードの任意のチャンクのエイリアスに使用できます。
モニカとの軽度のレース

2

Arduinoの2週間の初心者として、私はArduinoが非プログラマーに占拠されているという一般的な考えを取り上げました。Arduinoサイトにあるものを含め、私が調べたほとんどのスケッチは、完全に秩序の欠如を示しており、機能しないスケッチとまとまりのあるコメントがほとんど見えません。フローチャートは存在せず、「ライブラリ」はモデレートされていない寄せ集めです。


0

私の答えは...それが機能するからです。「なぜ「間違っている」必要があるのか​​」などの質問に答えないで苦労しています。


3
優れたプログラマーの特徴の1つは、コードが常にその意図を反映していることです。
イグナシオバスケス-エイブラムス

1
まだArduinosについて話しているのですか?;)
linhartr22

3
Arduinoは、コミュニティによって発表された平凡からひどいハードウェア設計のため、より大きなEEコミュニティで既に悪い評判を持っています。私たちは何かについてしゃべりましょう
イグナシオバスケス-エイブラムス

2
「ほとんどのプロジェクトは生命や財政のリスクを伴うことはありません...」そこには驚きはありません。コミュニティ全体を見た後、リスクの可能性があるArduinoに関与したい人は誰でしょう。
イグナシオバスケス-エイブラムス

2
それはある特定の状況ではなく、それを「正しい、」それはここでより多くの状況があることに比べて、ために動作しませんので、それは間違っている」ではないのですない仕事を。これにより、コードが脆弱になります。コードの変更は、デバッグ時間を浪費する不可解な障害を引き起こす可能性があります。コンパイラの型チェックとエラーメッセージは、これらの種類のエラーを後ではなく早期にキャッチするのに役立ちます。
カートJ.サンプソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.