أرشيفات الإلكترونيات الرقمية Uncategorized USING contemporary C++ methods WITH ARDUINO

USING contemporary C++ methods WITH ARDUINO

C++ has been rapidly modernizing itself over the last few years. starting with the introduction of C++11, the language has made a big step ahead as well as things have altered under the hood. To the typical Arduino user, a few of this is irrelevant, perhaps many of it, however the language still provides us some good features that we can take advantage of as we program our microcontrollers.

Modern C++ enables us to compose cleaner, much more concise code, as well as make the code we compose much more reusable. The complying with are some methods utilizing new features of C++ that don’t add memory overhead, decrease speed, or boost size since they’re all handled by the compiler. utilizing these features of the language you no longer have to concern about specifying a 16-bit variable, calling the wrong function with NULL, or peppering your constructors with initializations. The old methods are still offered as well as you can still utilize them, however at the extremely least, after reading this you’ll be much more conscious of the newer features as we begin to see them roll out in Arduino code.

How huge are your integers?

C++11 introduced a series of fixed width integer types aliases that will provide you the number of bits (in multiples of 8) you want. There are both signed as well as unsigned versions. If you utilize int16_t for a variable you understand it’s 16 bits, regardless of which Arduino is being targeted.

1.
2
3.
4
int8_t/uint8_t – a signed/unsigned type that is precisely 8 bits in size.
int16_t/uint16_t – a signed/unsigned type that is precisely 16 bits in size.
int32_t/uint32_t – a signed/unsigned type that is precisely 32 bits in size.
int64_t/uint64_t – a signed/unsigned type that is precisely 64 bits in size.

These are aliases of the underlying types, so on Arduino Uno, int8_t is the exact same type as a char, as well as uint16 is the exact same size as an unsigned int. One note, if you’re editing a ‘.cpp’ file, you’ll have to #include , however in a ‘.ino’ file, you don’t.

Anonymous Namespaces

The idea of an anonymous namespace has been around for a while in C++, however it concerned prominence with the introduction of C++11. In C++11, the anonymous namespace is now the favored method to specify a variable, function, or class that is accessible only in the present data (ie., they have internal, rather than external, linkage). It’s likewise a good method to consolidate things which only requirement to be accessed within the present file. anonymous namespace are likewise called ‘unnamed namespaces’ because, as the name suggests, they are defined without a name:

1.
2
3.
namespace {

}

Anonymous namespaces take the location of declaring things static. Anything you may have declared as static or const, or written as a #define can now put into an anonymous namespace as well as have the exact same impact – anything defined in inside cannot be accessed outside of the ‘.cpp’ data that the namespace is in. In the Arduino IDE, though, if you add a tab as well as provide the new tab a name that doesn’t end in ‘.cpp’ or ‘.h’ then the data is provided an extension of ‘.ino.’ When you click the ‘Verify’ button, all the ‘.ino’ data are concatenated into a single ‘.cpp’ file. This implies that anything you state as being static or const or in an anonymous namespace will be offered in each ‘.ino’ data because, when they are concatenated, they all end up in the exact same ‘.cpp’ file. This typically isn’t a issue for little Arduino programs, however it’s great to be conscious of it.

Okay, so now we understand about interior as well as outside linkages as well as exactly how data are concatenated before being compiled. exactly how does this assist us in our code? Well, we now understand exactly how to define variables to ensure that they won’t leak into areas they’re not expected to be.

rather than write:

1.
2
3.
4
5
6
// This ought to be utilized sparingly anyway
#define SOME_VAR 1000    
// static variables declared in a data are regional to the file
static int16_t count = 0;    
// const variables declared in a data are regional to the data as well
const int16_t numLeds = 4;  

you can now write:

1.
2
3.
4
5
6
7.
8.
9.
namespace {
  const int16_t SOME_VAR = 1000;  // now it’s type-safe
  int16_t count = 0;  // No requirement to utilize static
  const int16_t numLeds = 0;  // Still declared const.

  class thisClassHasACommonName {

  };
}

Everything’s contained within the anonymous namespace at the beginning of the file. The compiler won’t get confused if there’s one more SOME_VAR, count or numLeds defined in a different file. as well as unlike static, classes declared in an anonymous namespace are regional to the data as well.

Automatic for the people

The car keyword, added in C++11, enables you to define a variable without understanding its type. when defined, though, like other variables, it’s type can’t be changed, just like rمتغيرات outine c ++. يعتمد برنامج التحويل البرمجي C ++ خصم من نوع المتغير.

1.
2.
3.
Auto I = 5؛ // أنا من النوع الدولي
Auto J = 7.5F؛ // J هو من نوع تطفو
Auto K = GetResult ()؛ // ك هو كل ما نوع getResult () إرجاع

عند الشراء من أجلك لتحديد أنك تريد مرجعا، يمكنك القيام بذلك:

1.
2.
السيارات & amp؛ temp1 = myvalue؛
const auto & amp؛ temp2 = myvalue؛

يتم استنتاج النوع المناسب للنصائح أيضا:

1.
2.
int myvalue = 5؛
Auto MyValueptr = & amp؛ myvalue؛ // myvalueptr هو نصيحة إلى int.

السيارات هي اختصار رائع لأولئك الأنواع الطويلة الصعبة بشكل خاص. انها تعمل رائعة لتحديد مثيلات المحرك!

باستخدام استخدام.

كانت هناك بضعة طرق لإنتاج الأسماء المستعارة في C ++: المتواضع (والخطير) #Define وكذلك typedef أقل ضررا. فضل استخدام TypeDef ل # Define، ولكن لديهم بضعة قضايا. الأول هو القراءة. فكر في الامتثال لشركة TYPEDEF:

1.
typedef الفراغ (* fp) (int، const char *)؛

للوهلة الأولى، خاصة إذا كنت لا تستخدم C ++ كثيرا، فقد يكون الأمر صعبا لتحديد أن هذا ينتج عن اسم مستعار، FP، وهو نصيحة إلى وظيفة تقوم بإرجاع مساحة بالإضافة إلى ذلك معلمة سلسلة. الآن، دعونا نرى طريقة C ++ 11:

1.
باستخدام FP = باطل (*) (int، const char *)؛

يمكننا الآن أن نرى أن FP هو اسم مستعار لشيء ما، وكذلك هو أكثر بساطة بعض الشيء لتحديد أنه طرف وظيفة أنه اسم مستعار.

الفرق الثاني هو أكثر بكثير من الباطن، على الأقل في برمجة اردوينو. يمكن أن تكون القوات الأمريكية تماثيل بينما لا يستطيع TypeDefs.

nullptr.

في C وكذلك C ++ 98، يتم تعريف NULL حقا باسم 0. لتكون متوافقة مع الوراء، سيمكنك برنامج التحويل البرمجي C ++ من تهيئة متغير تلميح باستخدام 0 أو Null.

عند البدء في استخدام السيارات، ستبدأ رؤية التعليمات البرمجية مثل هذا:

1.
2.
3.
نتيجة تلقائية = getResult (…)؛

إذا (النتيجة == 0) {…}

فقط من إلقاء نظرة على هذا، لا يمكنك معرفة ما إذا كانت GetReSult إرجاع نصيحة أو عدد صحيح. ومع ذلك، حتى بين أولئك الذين ما زالوا يستخدمون C، لن يفتقد العديد منهم إذا كان النتيجة == 0، فسوف يقومون بتفتيش ما إذا كان النتيجة == NULL.

1.
2.
3.
نتيجة تلقائية = getResult (…)؛

إذا (النتيجة == null) {…}

إذا، في وقت لاحق، يمكنك التعديل GetReSult لإرجاع int، وليس هناك خطأ مترجم – لا يزال العبارة سارية، على الرغم من أنه لا يزال يبدو أنه يجب أن يكون مؤشرا.

C ++ 11 تعديلات من خلال إدخال Nullptr، وهو نوع طرف فعلي. الآن، تكتب:

1.
2.
3.
نتيجة تلقائية = getResult (…)؛

إذا (النتيجة == nullptr) {…}

الآن أنت تفهم أن GetReSult يمكن فقط إرجاع المؤشر فقط. بالإضافة إلى ما إذا كانت هناك بعض التعديلات عليك، فسوف يحصلون على خطأ في الترجمة إذا لم يكنوا كذلك تعديل بيان ما إذا كان ذلك. يعني إدخال Nullptr بالمثل أنه أكثر أمانا لتحميل تقنية على نوع متكامل بالإضافة إلى نوع نصيحة. علي سبيل المثال:

1.
2.
3.
4.
5.
الفراغ setvalue (INT I)؛ // (1)
Foid SetValue (القطعة * ث)؛ // (2)

setvalue (5)؛ // المكالمات الهاتفية 1
setvalue (null)؛ // بالمثل المكالمات الهاتفية 1

نظرا لأن NULL ليس مؤشرا، فإن الاتصال الخاص بنا ل SetValue الهاتف يستدعي الإصدار الذي يأخذ معلمة عدد صحيح. يمكننا الآن الاتصال الهاتف SetValue الثاني بشكل صحيح عن طريق الاستفادة من Nullptr:

1.
setvalue (nullptr)؛ // المكالمات الهاتفية 2

هذا هو السبب في أنه يعتقد عادة ضارة لتحميل وظيفة أو تقنية بناء على معلمة عدد صحيح بالإضافة إلى طرف (إلى أي شيء). إنه أكثر أمانا، ولكن لا يزال عبئا.

التهيئة الافتراضية

النظر في الامتثال للفئة:

1.
2.
3.
4.
5.
6.
7.
8.
فئة فو {
Foo (): Foostring (Nullptr) {…}
Foo (Const Char * Str): Foostring (Nullptr) {…}
foo (const foo & amp؛ أخرى): foostring (nullptr) {…}

نشر:
char * foostring.
}

لقد قمت بتهيئة كل المتغير مع Nullptr، وهو أمر جيد. إذا تمت إضافة متغير عضو آخر إلى هذه الفئة، يتعين علينا الآن إضافة ثلاثة عمليات تهيئة أخرى إلى المنشئ. إذا كان منصمك يحتوي على عدد من المتغيرات، فعليك إضافة تهيئة جميعها في جميع المنشئين. يوفر لك C ++ 11 الخيار لتهيئة المتغيرات مضمنة بالإعلان.

1.
2.
3.

نشر:
char * foostring = nullptr؛

مع C ++ 11، يمكننا تحديد قيمة أولية افتراضية – لا يزال بإمكاننا تجاوز هذا في كل منشئ إذا لم نتطلب ذلك، ولكن، إذا لم نفعل ذلك، فلا يهم بالضبط مدى إضافته العديد من الصانعين لتعيين القيمة في مكان واحد. إذا قمنا بفصلنا عن صفحتنا إلى بيانات “.h” بالإضافة إلى ملف “.cpp”، ثم فائدة إضافية هي أننا نوفر فقط بيانات “.h” لإضافة وكذلك تهيئة عامل.

تحديد عودة الخاص بك

تمكين أحد الأشياء التي يحاولها C ++ التي يجب القيام بها للمبرمج لتغليف الأشياء بحيث، على سبيل المثال، عند تسمية متغير، فأنت لا تسمية متغيرك بالضبط بشكل غير قصد مثل شيء آخر مع نفس الاسم بالضبط. يوفر لك C ++ أدوات لتمكينك من القيام بذلك، مثل أسماء الأسماء بالإضافة إلى الفصول الدراسية. ومع ذلك، فإن العادة المتواضعة تسرب مداخلهاinto the surrounding scope:

1.
2.
3.
4.
5.
6.
7.
enum Colour {
أبيض،
أزرق،
الأصفر
}
// Doesn’t compile.  There’s already something in this range with the name ‘white’
auto white = 5; 

The variable ‘white’ can’t be defined since ‘white’ is part of an enum, as well as that enum leaks it’s entrances into the surrounding scope. C++11 introduces scoped enums which enable a couple of things that C++98 didn’t allow. The first, as the name implies, is that the enums are completely scoped. The method to produce a scoped enum is with the utilize of the ‘class’ keyword:

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
enum class Colour {
أبيض،
أزرق،
الأصفر
}

auto white = 5; // This now works.

Colour c = white; // Error, nothing in this range has been defined called white.
Colour c = Colour::white; // صيح.

By default, scoped enums have an underlying type: int, so whatever size an int is on your platform, that’s the size that sizeof will return for your enum. before C++11, unscoped enums likewise had an underlying type, however the compiler tried to be wise about it, so it would identify what the underlying type was as well as not tell us – it might enhance it for size as well as produce an underlying type that was the smallest that might in shape the number of entries. Or it might enhance for speed as well as produce a type that was the fastest for the platform. All this implies is that the compiler understood what type an enum was, however we didn’t, so we couldn’t ahead state the enum in a different file. علي سبيل المثال،

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
file1.h:

enum Colour {
أبيض،
أزرق،
الأصفر
}

file2.h:

enum Colour; // Error, in this file, the compiler doesn’t understand what the type of Colour is.

void SomeFunction(Colour c);

The only method is to #include header1.h in header2.h. For little projects, this is fine, however in bigger projects, adding an entry to the Colour enum will imply a recompilation of anything that includes header1.h or header2.h. Scoped enums have a default size: int, so the compiler always understands what size they are. And, you can modification the size if you wish:

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
file1.h:

enum class Colour: std::int8_t {
أبيض،
أزرق،
الأصفر
}

file2.h:

enum class Colour: std::int8_t;

void SomeFunction(Colour c);

Now any type of data that includes file2.h doesn’t necessarily have to be recompiled (file2.cpp will have to, since you’ll have to #include file1.h in it in purchase get it to compile properly.)

ختاما

You do have option when moving ahead programming your microcontroller. There’s no reason to utilize any type of of these if you don’t want to. I’ve found, however, that they assist clean up my code as well as assist me catch bugs at compile time rather than at run time. numerous are just syntactic sugar, as well as you may not like the change. Some are just niceties that make working in a challenging language a bit nicer. What’s holding you back from trying them out?

Leave a Reply

Your email address will not be published. Required fields are marked *