Basic programming understanding

Learning every time I load an example sketch...and I thank you all for that, but

and I tried to Google it, I do not seem to ask the correct question.

First I was shown....

const int LEDPin = 3;

Then I started to find

define LEDPin 3 //Taking note of no = or ;

Now I found

const int
LEDPin (3); //If I add a , i can add more constants The last one gets a ;

Does all this code mean the same or are there some hidden advantages to one or the other?

Have a read though here:

If you have lots of pins to declare , you can write

const int Pin1 = 3;
const int Pin2 = 4;
const int Pin3 = 5;

Guess it makes things tidier but I still prefer defining it on each line.
As:

const int Pin1(3), Pin2(4), Pin2(5);

The end of the line gets a ;

They all have the same effect.

The #define version tells the compiler to substitute 3 everywhere it finds LEDPin

The const int LEDPin = 3; creates space of a constant of size int (i.e. 2 bytes) with the value 3. In practice, because it is a constant and can never change the compiler probably won't actually allocate memory for it.

An advantage of int LEDPin over #define LEDPin is that the compiler can throw an error if the value is used incorrectly. With #define there can be no type-checking.

And just to confuse things further this particular example would be better as const byte LEDPin = 3;. It is unnecessary to allocate 2 bytes for a value that can never exceed 255 and saving bytes can be vital in the small memory of an Arduino.

...R

Robin2:
And just to confuse things further this particular example would be better as const byte LEDPin = 3;. It is unnecessary to allocate 2 bytes for a value that can never exceed 255 and saving bytes can be vital in the small memory of an Arduino.

Good tip. I keep forgetting about this as well. Updated my last program now and saved 100 bytes :slight_smile:

Thanks for that link, it pretty much explains it all. Will have to read it a couple of times to grasp it all. :confused:

gregmcc:
Have a read though here:

#define vs. const variable - Syntax & Programs - Arduino Forum

If you have lots of pins to declare , you can write

const int Pin1 = 3;

const int Pin2 = 4;
const int Pin3 = 5;




Guess it makes things tidier but I still prefer defining it on each line.
As:



const int Pin1(3), Pin2(4), Pin2(5);




The end of the line gets a ;

It looks like the examples are back to front and the single line version does not compiie

UKHeliBob:
It looks like the examples are back to front and the single line version does not compiie

I made a typo. Should be

const int Pin1(3), Pin2(4), Pin3(5);

gregmcc:
I made a typo. Should be

const int Pin1(3), Pin2(4), Pin3(5);

No, should be const byte Pin1(3), Pin2(4), Pin3(5); (and you should be thinking of less confusing names)

In C++ code you actually have more variants than that

#define LEDPin 3

const int LEDPin = 3;
const int LEDPin(3);
const int LEDPin{3};
const int LEDPin = {3};

constexpr int LEDPin = 3;
// and so on: the same variants with `constexpr`

enum 
{
  LEDPin = 3
};

Some of these variants are supported from C++11 on. But our compiler in Arduino IDE is C++11.

1. If you are writing pure C code, then you should prefer to use #define or enum (see below).

If you are writing cross-compilable code, that might be compiled as C or C++, then you should prefer to use #define or enum. For example, when you are writing header files, that might be included into C code and C++ code.

C language also has const. However, the problem with const declarations in C language is that in C const does not create a compile-time constant (as opposed to C++). C language will not let you use const value in contexts where constant expressions are required. This is a major reason why in C code we have to resort to #define.

2. Also remember that in C const objects have external linkage by default, which might lead to naming conflicts with other modules and libraries. If you decide to declare file-scope const object in C code, in most cases it is a good idea to declare them as static const.

In C++ adding static is not necessary, since in C++ all file-scope const objects already have internal linkage by default.

3. If you are writing your code in C++ only, you should normally avoid the #define version and use const or, better, constexpr. There's no reason to use #define to declare manifest constants in C++. The const approach gives you everything that #define does (e.g. it creates a compile-time constant) and also nicely obeys all scoping and type-safety rules of the language.

Now in this example all these versions are equivalent

const int LEDPin = 3;
const int LEDPin(3);
const int LEDPin{3};
const int LEDPin = {3};

However, in general case the () version might hide some unpleasant surprises (see Most vexing parse - Wikipedia). So, it is might be a good idea to stick to = and {} versions in C++. But it you are paying attention, it becomes a matter of personal taste.

Also, if your intent is to introduce a compile-time constant, starting from C++11, you should prefer to use constexpr, not const. The whole purpose of constexpr keyword is exactly that. E.g.

constexpr int LEDPin = 3;

4. Don't forget that in C and C++ you have another valuable way to declare integral constants: enums.

enum Pins
{
  LED_Pin = 3,
  Button_Pin = 4,
  Motor_Pin = 5
};

If enum approach fully covers your intent, then in C code it is a better idea to use enum than #define.

Robin2:
And just to confuse things further this particular example would be better as const byte LEDPin = 3;. It is unnecessary to allocate 2 bytes for a value that can never exceed 255 and saving bytes can be vital in the small memory of an Arduino.

This is a bit misleading.

In C++ language const int LEDPin = 3; declares a compile-time constant. In more formal terms, it declares an identifier that can be used in integral constant expressions. The compiler is not required to allocate anything at all, unless it is really necessary. In C++ language const int objects requires memory only if it is "ODR-used" (using formal terminoilogy), i.e. if you take its address in one way or another, e.g. use the unary & operator on it or bind references directly to it.

If you are using LEDPin as a mere value, no modern compiler will "materialize" this LEDPin as an object. No modern compiler will create a memory location for such LEDPin. So, it does not matter whether you declare it as byte, int, unsigned long and so on. It will not have any impact on program memory.

This applies to all scalar types. For larger types the situation is more complex. const objects of class and array types will typically materialize in memory. But in such cases it depends on the compiler.

OK, I'm confused.... Where does this syntax come from?

const byte Pin1(3), Pin2(4), Pin3(5);

I've been proigramming in c since the late '70s, and in c++ since the very early '90s, and I've never seen this syntax before, and Googling turns up no similar examples. What am I missing? And why on earth is yet another way of defining constants necessary, much less desirable?

Regards,
Ray L.

RayLivingston:
OK, I'm confused.... Where does this syntax come from?

const byte Pin1(3), Pin2(4), Pin3(5);

I've been proigramming in c since the late '70s, and in c++ since the very early '90s, and I've never seen this syntax before, and Googling turns up no similar examples. What am I missing? And why on earth is yet another way of defining constants necessary, much less desirable?

Regards,
Ray L.

Think of how you pass parameters(arguments) to a C++ constructor.
You're constructing a byte object.

AWOL:
Think of how you pass parameters(arguments) to a C++ constructor.
You're constructing an int object.

I assumed it was an attempt to "object-orient-ize" scalars. Until yesterday, I had never seen it, despite having used c++ off and on for nearly 30 years. Seems like I recall having seen similar approaches used at times, but those were implementation-specific approaches, IIRC, using things like "Int" instead of "int", etc.. But when did that syntax become part of the language?

Regards,
Ray L.

@montmorecncy will be along shortly with a complete explanation.

RayLivingston:
OK, I’m confused… Where does this syntax come from?

const byte Pin1(3), Pin2(4), Pin3(5);

I’ve been proigramming in c since the late '70s, and in c++ since the very early '90s, and I’ve never seen this syntax before, and Googling turns up no similar examples. What am I missing? And why on earth is yet another way of defining constants necessary, much less desirable?

It is really strange that you could not come up with examples by googling. This basic C+±specific syntax is described and explained to death on the Net. It existed in C++ from the very beginning.

It was introduced in C++ in order to unify the initialization syntax of objects of scalar types and initialization syntax of objects of class types. This unification is extremely important when writing generic code, i.e. template code in C++. Template code is written in terms of “unknown” (parameterized) types, so having a common syntax that is applicable to all types is important.

Note also, that this is the only syntax that you could use in “classic” C++ to initialize data members of the class in constructor initializer list.

You can think of it as “construction” of a byte object, albeit pedantically speaking it is incorrect. Scalar objects have no constructors. The unifying concept in C++ is properly called “initialization”, not “construction”. “Construction” in C++ is applicable to class types only.


In the end the original effort at unification through () initializers proved to be an inadequate half-measure, specifically because of the problems with “Most Vexing Parse” . So, in C++ another unification step has been taken in 2011: the so called uniform initialization syntax based on {} initializers has been introduced into the language. It is considered by many to be The Canonical, The Only True C++ initialization syntax. So, don’t be surprised to see

const byte Pin1{3}, Pin2{4}, Pin3{5};

in modern C++ code. This syntax has many valuable properties. Whether you want to completely switch to this syntax in your code is a matter of your personal preference. In many contexts you’ll have no choice.

Montmorency:
It is really strange that you could not come up with examples by googling. This basic C++-specific syntax is described and explained to death on the Net. It existed in C++ from the very beginning.

Interesting... Must not be widely used in the real world. I've participated in, and managed numerous large commercial software projects using c++, and never once come across that syntax.

Live and learn!

Regards,
Ray L.

RayLivingston:
Interesting… Must not be widely used in the real world. I’ve participated in, and managed numerous large commercial software projects using c++, and never once come across that syntax.

Well, if you worked with classes, then this syntax is widely used in constructor initializer lists

class C
{
public:
  C(double d) : 
    i(42),          // <-- Here it is
    j(d),           // <-- Here it is
    p(0)            // <-- Here it is
  {
  }

private:
  const int i;
  double j;
  void *p;
};

I’m sure you have seen this before, since (as I said above) in “classic” C++ there’s simply no way to write a constructor initializer list without resorting to this syntax.

And this syntax is not restricted to constructor initializer lists. You can use it anywhere.

Can I write a constructor initialiser list using {} ?

AWOL:
Can I write a constructor initialiser list using {} ?

Yes, starting from C++11 you can use {} in place of (). On top of that the {} syntax and C++11 provide you with some extra capabilities

class C
{
public:
  C() : 
    a{ 1, 2, 3 }  // <- possible only in C++11 and only with `{}` syntax
  {
  }

private:
  int a[3];
};

Thanks again to all,

to those that enlightened me

and

to those that made me feel not like a total idiot asking such a programming 101 question.