Const int, enum veya #define çok daha mantıklı olduğunda neden pin için bir int değişkeni kullanmalısınız?


24

Neden insanlar kodun yürütülmesi sırasında pimin değişmesi muhtemel olmadığında pin numarasını belirlemek için bir değişken kullanırlar?

Çoğu zaman intbir pin tanımı için kullanıldığını görüyorum ,

int led = 13;

ne zaman bir const int

const int led = 13;

veya enum, veya#define

#define LED 13

çok daha mantıklı.

Arduino sitesindeki derslerde bile, örneğin, çoğu insanın çalıştığı ilk ders olan Blink .

Ben bir yere okumakconst int daha fazla tercih edilir #define. Bu neden insanların en baştan kötü alışkanlıklar geliştirmelerine izin vermek yerine, en baştan teşvik edilmiyor? Bir süre önce fark ettim, ancak son zamanlarda beni rahatsız etmeye başladı, bu yüzden soru.

Bellek / işlem / bilgi işlem bilge bir const int, enumya da bu nedenle #define, bir düz, daha iyi int, yani daha az bellek kaplar, farklı bellekte saklanır (Flash, EEPROM, SRAM), daha hızlı yürütme, daha hızlı derleme?


Bu bir kopyası gibi görünebilir. Sabitler için #define veya const int kullanmak daha mı iyi? Ancak insanların neden değişkenleri kullandıkları ve hangi sabit değerlerin daha iyi olduğundan ziyade performanslarının nasıl geliştiği sorusunu ele alıyorum.


9
Çünkü korkunç korkunç olur. Çoğu hobi deneyimli programcı değildir ve diğer hobilere kötü alışkanlıklar kazandırır.
Ignacio Vazquez-Abrams

1
Özellikle pimleri ile digitalWrite gibi temel arduino API fonksiyonlarının basit formu doğru gömülü tasarım, yani kullanarak maskeleri ve tüm port için tek bir bellek adresi teşvik etmeyin
crasic

Yanıtlar:


20
const int led = 13;

Doğru yöntem budur. Ya da:

const byte led = 13;

Kaç tane pim var?

Öğreticilerden bazıları, olabilecekleri kadar kalite kontrolünden pek geçmedi.

Performans kullanmak daha iyi olacak const byte, kıyaslayacağınız intzaman derleyici ne yaptığınızı anlayacak kadar akıllı olabilir.

Yapabilecekleriniz, insanları kendi kodunuzda kullanarak daha verimli teknikleri kullanmaya yavaşça teşvik etmek.


Yorumlara verilen cevaplar

  1. Bir yorumcu, bytestandart C olmadığını önerdi . Bu doğru, ancak bu bir Arduino StackExchange sitesi ve Arduino IDE tarafından sağlanan standart türlerin kullanılmasının kabul edilebilir olduğuna inanıyorum.

    Arduino.h'de şu satır var:

    typedef uint8_t byte;

    Bunun tam olarak aynı olmadığını unutmayın unsigned char. Bkz: uint8_t - imzasız karakter ve ne zaman uint8_t - imzasız karakter nedir? .

  2. Başka bir yorumcu, bayt kullanımının performansı arttırmayacağını belirtti, çünkü sayılardan daha küçük sayılar intteşvik edilecektir int(bu konuda daha fazla bilgi istiyorsanız, Tamsayı Promosyon Kurallarına bakınız).

    Bununla birlikte, bir const tanımlayıcısı bağlamında , derleyici her durumda etkin kod üretecektir. Örneğin, "yanıp sönme" yi sökmek bunu orijinal biçimde verir:

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

    Aslında, aynı kodu üretir 13:

    • Değişmez
    • Bir #define
    • Bir const int
    • Bir const byte

Derleyici bir sicile ne zaman bir sayı sığabileceğini ve ne zaman yapamayacağını bilir. Ancak , amacınızı belirten kodlama kullanmak iyi bir uygulamadır . O Making numara değişmeyeceğini temizlemek yapar ve bunun yapımı (veya ) bu size az sayıda beklediklerini temizlemek yapar.constbyteuint8_t


Kafa karıştırıcı hata mesajları

Kaçınılması gereken diğer bir önemli neden, #definebir hata yaparsanız aldığınız hata mesajlarıdır. Bir hata olan bu "göz kırpma" taslağını göz önüne alın:

#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);              
}

Yüzeyde Tamam görünüyor, ancak bu hata iletilerini oluşturur:

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

Vurgulanan ilk satıra (satır 4) bakarsınız ve hatta bir "=" sembolü görmezsiniz . Artı, çizgi iyi görünüyor. Şimdi sorunun burada ne olduğu ( = 13bunun yerine geçmekte olduğu LED) oldukça açık , ancak satır kodda 400 satır daha ileride olduğunda, sorunun LED'in tanımlandığı şekilde olduğu açık değil.

İnsanları bu kadar düşerken gördüm (kendim dahil).


Kaç tane pim var? Çok iyi bir nokta Nick, çoğu kurul yüzlerce (yani 255'ten büyük) değil, sadece onlarca menzile sahip olduğu için, yani intArduino nihayet Tera tahtası ile çıkıncaya kadar ... fazladan saygısız bir ... :-)
Greenonline

2
C'nin bir bytetipi yok . Yani unsigned char.
Kevin

Performans, çoğu bağlamda, terfi edilenden daha küçük türlere sahip tamsayı değerlerinden bytedolayı int, bununla daha iyi olmayacaktır . intint
Pete Becker,

1
C doesn't have a byte type. You mean unsigned char.- Cevabım buna sahip olan Arduino bağlamındaydı typedef uint8_t byte;. Yani bir Arduino için kullanmak bytetamam.
Nick Gammon

Performance won't necessarily be better with byte instead of int- değiştirilen yayına bakın.
Nick Gammon

19

Ignacio'nun haklı olarak belirttiği gibi, temel olarak daha iyi bilmedikleri içindir. Ve onlar daha iyisini bilmiyorlar çünkü onlara öğreten insanlar (veya öğrenirken kullandıkları kaynaklar) daha iyisini bilmiyorlardı.

Arduino kodunun ve öğreticilerin çoğu, programlama konusunda hiç eğitim almayan ve programlama konusunda uygun bir eğitim almamış, kendileri tarafından çok fazla öğretilen insanlar tarafından kaynaklardan çok fazla "kendi kendine öğretilmiş" kişilerce yazılmıştır.

Yer çevresinde gördüğüm öğretici kod parçacıklarının birçoğu (ve özellikle yalnızca YouTube videoları içinde bulunanlar için) bir sınavda işaretlemiş olsaydım başarısız bir not olurdu.

Evet, a constconst olmayan ve hatta a tercih edilir #define, çünkü:

  • A const(gibi #define, bir mazeretin aksine) herhangi bir RAM ayırmaz
  • A const(const olmayan, ancak a'dan farklı olarak #define), değere açık bir tür verir

Buradaki ikinci nokta özel ilgi alanıdır. Özellikle gömülü type-cast ( (long)3) veya type sonix ( 3L) veya bir ondalık nokta ( 3.0) ile açıkça belirtilmediği sürece #define, bir sayının her biri bir tamsayı olacak ve bu değer üzerinde yapılan tüm matematikler sanki tamsayı. Sorun olmayan çoğu zaman, ancak #definebir tamsayının depolayabileceğinden daha büyük bir değere çalıştığınızda ilginç senaryolar ile karşılaşabilirsiniz #define COUNT 70000ve daha sonra intüzerinde diğer değerlerle matematiksel bir işlem gerçekleştirin . Bir kullanarak constderleyiciye "Bu değer bu değişken türü olarak kabul edilir" - yani bunun yerine şunu kullanırsınız: const long count = 70000;tümü beklendiği gibi çalışır.

Aynı zamanda değeri, yerin etrafından geçirirken tipini kontrol ettiği vuruş etkisi vardır. const longA'yı bekleyen bir işleve geçmeyi deneyin intve değişken aralığının daraltılmasından şikayet eder (hatta senaryoya bağlı olarak derlenemez). Bunu bir ile yapın #defineve sessizce size yanlış sonuçlar vermeye devam edin ve saatlerce başınızı tırmalamadan bırakın.


7
Bir belirterek It değerinde constdeğişken olabilir olmayan bir constexpr fonksiyonun geri dönüş değerini kullanarak başlatıldı eğer bağlamda, örneğin bağlı olarak RAM gerektirir.
Peter Bloomfield

Benzer şekilde, const int foo = 13; bar(&foo);kesinlikle derleyicinin için gerçek belleği ayırması gerekir foo.
Ilmari Karonen,

3
Bir intderleyiciye sığmayacak bir değere genişleyen bir makro tanımlarsanız, değerin sığabileceği en küçük tipe sahip olduğunu kabul eder (imzalı ve imzasız olanlar hakkında modulo kuralları). Eğer int16 bitlik bir sistemdeyseniz , tıpkı olarak tanımlanmış gibi bir gibi görünmeye #define count 70000neden olur . Ayrıca, bu sürümlerden herhangi birini bir fonksiyonun beklediğine geçirirseniz , herhangi bir mantıklı derleyici onlara aynı şekilde davranır. countlongconst long count = 70000;countint
Pete Becker,

1
@PeteBecker ile aynı fikirdeyim - benzeri bir yapı #define COUNT 70000int anlamında kesilmez , ancak derleyici bu sayıyı tutacak kadar büyük bir tür olarak değerlendirir. COUNTBir int kullanmadığın zaman açık olamayacağı doğrudur , ama const longyine de aynı şeyi söyleyebilirsin .
Nick Gammon

2
"Bir #define her zaman bir tamsayı olacak" Bu doğru değil. Tamsayılı değişmezlerin kurallarını alıyor ve bunları önişlemci makrolarına uyguluyorsunuz. Elma ve pop müziği karşılaştırmak gibi. İfadesi COUNTsizin örnekte ifade ile derleme önce değiştirilir 70000gibi, değişmezleri kurallarına tanımlanan bir türü olan, 2ya da 13Lya da 4.0değişmezleri kuralları ile tanımlanmıştır. Bu #defineifadeleri takma ad kullanmanız gerçeği önemli değil . İsterseniz, #defineC kodunun isteğe bağlı parçalarını takma ad olarak kullanabilirsiniz .
Monica ile Hafiflik Yarışları

2

Arduino'nun 2 haftalık bir acemi çocuğu olarak, genel olarak Arduino'nun programcı olmayanlar tarafından işgal edildiği fikrine kapılıyorum. Arduino'dakiler de dahil olmak üzere incelediğim eski çizimlerin çoğu, çalışmayan eskizler ve görünürde neredeyse tutarlı bir yorumla birlikte toplam bir düzen eksikliği gösteriyor. Akış şemaları mevcut değildir ve "Kütüphaneler" denetlenmeyen bir karmakarışıktır.


0

Cevabım ... onlar işe yarıyor çünkü yapıyorlar. Cevabımda "neden" yanlış "olmak zorunda?" Gibi bir soru sormamakta zorlanıyorum.


3
İyi bir programcının ayırt edici özelliği, kodun daima niyetlerini yansıtmasıdır.
Ignacio Vazquez-Abrams,

1
Hala Arduinos hakkında konuşuyoruz, değil mi? ;)
linhartr22

3
Arduino, geniş EE topluluğunda, toplum tarafından ortaya konulan vasat-korkunç donanım tasarımları nedeniyle zaten kötü bir üne sahip. Bir şey hakkında bir şeyler bırakmayalım mı?
Ignacio Vazquez-Abrams,

2
“Çoğu proje can ve risk riskini içermeyecek…” Orada sürpriz yok. Kim topluluğa baktıktan sonra Arduino'yu riske girme ihtimalinin olduğu yerlere dahil etmek ister .
Ignacio Vazquez-Abrams

2
O belirli bir durumda işi değil ama bunu yaparken kıyasla çünkü 'sağ' hangi daha durumlar vardır çünkü 'yanlış' değil değil işi. Bu kod kırılgan yapar; Koddaki değişiklikler, hata ayıklama süresini tüketen gizemli arızalara neden olabilir. Derleyicinin tür denetimi ve hata mesajları, bu tür hataları daha sonra değil, daha erken yakalamanıza yardımcı olmak için vardır.
Curt J. Sampson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.