const int / int

What's difference does it make defining a pin using "int" or "const int"?

What’s difference does it make defining a pin using “int” or “const int”?

Look at this bit of common, although incorrect code, and see if you can answer that question.

int pin = 8;
if(pin = HIGH)
{
}
int speedPin = A2;     // analog pin used to connect the speed channel
int motorPin = 3;      // digital pin used to connect the DC motor
int speedVal;          // variable to read the value from the analog pin 

int elevPin = A0;  // analog pin used to connect the elevator channel
int elevval;    // variable to read the value from the analog pin 

int ailPin = A1;  // analog pin used to connect the aileron channel
int rightailval;    // variable to read the value from the analog pin 
int leftailval;    // variable to read the value from the analog pin

In my code, the speedPin, elevPin, and ailPin are all getting inputs to check the analog values sent from my remote control to control my motors and servos. The Arduino Uno is 'constantly' checking the values. Should they be defined as "const int"s or just plain "int"s?

1 Like

The difference between int and const int is that int is read/write while const int is read-only.

If you want the compiler to catch invalid attempts to write to a variable, make it const. If the variable needs to be written to, as one that is legitimately used on the left of an equal sign, then it must not be const.

Pin numbers should rarely be changed. Ergo, they should usually be const. Only you can really tell, though.

There might be circumstances in which you do want to change the value in a variable with pin in its name.

1 Like

Another thing really worth noting is that if you use "const", because the variable is read only, the
compiler can make optimizations which includes not allocating any data storage for the variable.

When you don't use "const" even though code in the module that declares the variable may not modify
the variable, it is possible that some other module (.c or .cpp file) might modify that variable. Because of that,
the compiler must allocate data storage for the variable.

RAM is very limited on the AVRs so it is best to const when using variables to hold read-only values to save ram space.

--- bill

1 Like

pls. and what is the difference between

const int PWMpin=5; // D5

and

#define PWMpin 5 // D5

Here we go again . . .

Hi kllsamui!

The difference is:

#define:
this is not a real variable, it is just a placeholder. When you compile your sketch, the name will be replaced by its value. Thats why I use #define for pin-definitions.
example:
Your sketch:

#define LEDpin 13

...
void loop() {
  digitalWrite(LEDpin)
}

The compiler will compile this:

void loop() {
  digitalWrite(13)
}

not more, not less!

const int LEDpin=13
Now LEDpin is a real Variable and uses RAM. But you can use it as a “normal” variable as int, boolean, … Thats why const is better for fix values like pi.

FlyingAngel:
You are wrong.

const ints don't use RAM.

KeithRB:
FlyingAngel:
You are wrong.

const ints don't use RAM.

Sorry, that's not true - they're a bit like Schoedinger's cat - they don't reside in RAM, unless you ask them their address.

Consider:

int a = 10;
const int b = 11;
int c = 12;

void setup ()
{
  Serial.begin (115200);
  Serial.println ((unsigned long)&a, HEX);  
  Serial.println ((unsigned long)&b, HEX);  
  Serial.println ((unsigned long)&c, HEX);  
}

void loop ()
{  
}

Hah! Thanks for the analogy.

But using a pointer with a const int is probably pretty rare, and actually points out another difference between a const and #define.

KeithRB:
Hah! Thanks for the analogy.

But using a pointer with a const int is probably pretty rare, and actually points out another difference between a const and #define.

But it's not at all rare to use a pointer to a "const char".

Serial.println ("Hello World!");

@KeithRB: AWOL's example is not really using a pointer. A true data item has an lvalue (an address where it lives in memory) and an rvalue (what is contained at that address). Simple assignment statements:

int a = 10;
int b;

b = a;

are rvalue to rvalue exchanges. The same is true in a function call:

Serial.print(b);

AWOL's example simply places the address of operator (&) in front of the variable to tell the compiler not to use the rvalue of the data item, but rather the lvalue in the call to the Serial object. It has nothing to do with pointers.

It also should be pointed out that a #define is typeless whereas a const is always tied by its definition to a data type. While a #define does give up the safety of type checking, there are some cases where this can make a data structure more flexible.

Finally, to the OP, most programmers will use all cap letters with both #define and const as a tip-off that the data item is "different" than other variables.

I disagree, econjack. A string constant has a type of "array of characters" and so decays to a pointer to its first element when used as in AWOL's example.

econjack:
@KeithRB: AWOL's example is not really using a pointer. A true data item has an lvalue (an address where it lives in memory) and an rvalue (what is contained at that address). Simple assignment statements:

int a = 10;

int b;

b = a;




are rvalue to rvalue exchanges. The same is true in a function call:

That's not quite my understanding. An rvalue is something that can only be the right hand side of an assignment - it is a transient value. For example, (x+1) is an rvalue. An lvalue is something that can be the left hand side of an assignment - it refers to a variable or memory location. I know it's become much more complicated than that but I think the fundamental concepts of lvalue and rvalue are still the same.

A string constant has a type of “array of characters” and so decays to a pointer to its first element when used as in AWOL’s example.

Perhaps a difference in point of view. First, AWOL’s example doesn’t use any arrays, so I fail to see how it is decaying into a pointer. Second, you are equating a memory address with a pointer. They are not the same. A memory address is just that…a memory address and its size is fixed by the host machine: 16 bits on an Arduino but 32 bits on other controllers. A pointer, however, always has a scalar as part of its attribute list. A pointer to int has a 2-byte scalar while a pointer to long has a 4-byte scalar. The scalar attribute is necessary to perform proper pointer arithmetic.

@PeterH: I don’t view it that way. In the statement:

delay(b);

int k = 10;

what is the rvalue of b? The lvalue tells me where to find b in the memory map, while the rvalue tells me the value of what the bytes allocated to b hold at that address. In the second expression, k still has an lvalue where it is located in memory, but it also has an rvalue even though it’s on the left side of the assignment expression. Until the value 10 is moved to k’s lvalue, the rvalue of k is whatever random pattern of bits happens to exist at those two bytes of memory. All defined data items have an lvalue and an rvalue regardless of there they appear in an expression.

Take it up with K&R, then.

"This is a string constant"

has a type of array of characters, and in fact you can even do something like this:

"abcdef"[5]

to refer to the 'f'.

or

5["abcdef"]

If you want to obfuscate.

http://c-faq.com/aryptr/joke.html

I'm unclear why a discussion as to whether or not "const"s reside in RAM has turned into a discussion about [l|r]values.
They clearly can, or simple things like Serial.print couldn't work.

yes, sorry, i can not understand all of the argumentation,
and a clear " BETTER USE THIS .." is missing

so i made test code ( actually 8 versions )

  • use IDE internal PI
  • use float pi
  • use const float pi
  • use #define pi

use at runtime

  • copy it to one variable
  • copy it to two variable

and a time measuring for 1.000.000 loop cycles
( using a leonardo and IDE 157 )
and found there is no difference in using internal PI, const float PI or #define PI
but float pi is definitely bigger in RAM, ROM, cycle time.
pls. see RAMROM - Google Sheets