Odd question. When initially defining the pins on a sketch normally I used "const int = 2;" ect. If I were to only use these pins for digital use only, could I define them as "const bool =2;" in the interest of saving memory on a large program. Everything that I have googled indicates that it should work. My question is will it work in the testing but once the heavy lifting of the program starts then unseen errors will occur. You insight to this would be helpful.
Thanks in Advance
machinetech
I think there’s a confusion between pins being digital and declaring a constant value in your program. These are two unrelated concepts. What do you mean by bool = 2? bool can be true or false. Also not clear if memory is saved if you change type of a constant value like 2.. at any rate if you don’t like int you can use byte but I think there’s a confusion between pin number and pin being digital (bool)
bool can’t support a value of ‘2’ by definition.
Boolean values can only contain binary states TRUE or FALSE, ZERO, or NON-ZERO.
You can impose or infer states from those values, but the underlying Boolean value can’t be anything else.
Hello amachinetech
For the declaration for port pins you might use:
const uint8_t PortPins[] {2,3,4,5,6,7};
Have a nice day and enjoy coding in C++.
The pin numbers are not booleans. The value read from a digital pin can be stored as a boolean.
The compiler is good in saving memory. If a "const" variable can be eliminated then it is eliminated. I also observed int truncated to a byte, if possible.
On an UNO through the IDE 2.0
bool b = 2;
void setup() {
Serial.begin(115200);
Serial.print("b = ");
Serial.println(b);
}
void loop() {
}
OUTPUT:
b = 1
I think what the OP is looking for is byte not bool.
const byte or const uint8_t reduces memory on an 8-bit AVR, but AFAIK not on 16-bit boards.
Leo..
+1 for const
I mean that const byte or const int makes a difference on an 8-bit MCU, but not on a 16-bit MCU.
Leo..
As Arduino uses uint8_t I suggest to use uint8_t with const or constexpr
void digitalWrite(uint8_t pin, uint8_t val)
int digitalRead(uint8_t pin)
int analogRead(uint8_t pin)
void analogWrite(uint8_t pin, int val)
from
ArduinoCore-avr/wiring_private.h at master · arduino/ArduinoCore-avr · GitHub
and
ArduinoCore-avr/wiring_analog.c at master · arduino/ArduinoCore-avr · GitHub
The reason that compiles is due to how C/C++ interprets logical values.
Basically a 0 is false and non zero is true. So, your line of code
bool b = 2;
Is effectively the same as
bool b = true;
However since a bool has only two states and thus could be stored in a single bit, it will print as 0 (for false) and 1 (for true). And, that would be the entire range of the values you can get out of it.
So, it doesn't matter if you set it to 2 (or any other non-zero value), it will be transformed to a 1.
This is why code constructs like this can work (Edit: Added 2 prints to improve the output to better illustrate the point)
char *p = "hello";
while (*p++) {
// do something with *p for example
Serial.print(*p);
Serial.print("=0x");
Serial.println(*p, HEX);
}
Which will print the letters of "hello" on separate lines. The loop ends because the string has a null byte (0x00) at the end of it. When the pointer reaches the null following the letter 'o', the while will evaluate to false (because a 0 is false) and end.
Edit: added this explanation (along with the two print statements in the above example code) to hopefully better illustrate the point - which is why the while(p*++) can terminate.
So what the above loop will do is as I previously said, will step through the characters of the string "hello" one by one. It will print what it is pointing to within the body of the loop in two formats (the character itself and its hex character code).
However, what I neglected to state is that while it will use the "current" character to evaluate whether or not to execute the body of the loop, when/if it does execute the body of the loop, it will execute it with the pointer pointing to the "next" character in the string.
In more detail, the while loop will first examine the character that p is pointing to. In the first instance, this will be the letter "h". Since "h" is not the terminating null (at the end of the string), the evaluation will be "true" and thus the loop body will be executed. However, before the loop body executed, the pointer p
will be incremented - so even though it has evaluated the very first character of the string to decide whether or not to execute the body, the body of the loop will be executed with the pointer pointing to the second character - i.e. the "e" in the string "hello". Consequently, the first line of output (of the modified code) will be e=0x65
.
Next the loop will evaluate what p is pointing at for true/false since p is pointing to the e - which has a value of 0x65 and thus is not 0, it will again evaluate to true and execute the body of the while
loop - but before it does that p will be incremented, so now it is pointing at the first "l" which it will print as follows l=0x6C
This will continue until we have printed the last character i.e. o=0x6F
. At this point, the pointer p
is still pointing to the letter "o". So the above process repeats the while will evaluate what p is pointing to (i.e. the letter "o") identify that it is non-zero and thus true, so it enters the loop (for what will be the final time). As before p is incremented before entering the loop, so now it is pointing to whatever is beyond the last letter of the string "hello" - this will be the null terminator at the end of the string. So the output will be =0x0
.
Now the pointer - which is pointing to the null terminator on the string - is pointing to a byte in memory whose value is 0x00 - which from above if used in a logical context (i.e. the test of a while loop or an if etc) will be interpreted a false. At this point because p is pointing to that 0 byte, the while condition will evaluate to false and the loop will terminate - which is why the =0x0
line is the last one printed. Of interest, the ++
part of *p++
will still be applied and increment p. So if you tried to use *p it will now be pointing to whatever is following the trailing null in the string "hello", which to all intents and purposes would be a random value (and not valid or appropriate to use for anything useful).
As others have indicated in other comments, the above code is not how you would normally step through the characters of a string, but it does illustrate (IMHO) how the zero/non-zero values are evaluated as false/true in a logical context such as the conditional expression of a while
statement.
I hope that makes sense. If not, put that code in a setup()
function and have a bit of a play with it.
This is very dangerous and broken code
"hello" is orphaned (no more accessible) after the loop,
and due to auto increment the output starts with the second character and ends with a funny \0.
Please do not post buggy code for educational purpose!
Here the difference is 1 byte, on a 32 bit MCU it's 3 bytes. So yes, it makes a difference - unless the compiler optimizes away unused bytes.
The bool datatype as referred to by the OP is stored as 8 bits on a 8 bit microcontroller. It is the same size as the byte or uint8_t datatypes.
While you can manually manipulate the individual bits in any variable in order to store boolean values in a single bit. They are not recognized as boolean's by the IDE.
I did say could not is
No, it could not - I'm C/C++, a pointer cannot point to a single bit, so a bool could not be a single bit
You are correct about the increment. It would have been better to increment in the loop.
char *p = "hello";
while (*p) {
// do something with *p for example
Serial.println (*p++);
}
Or
char *p = "hello";
while (*p) {
// do something with *p for example
Serial.println (*p);
p++;
}
As for p not being accessible ... will depend on where it is declared (globally or within the body of a function). But as for it no longer being accessible outside of the block it is defined in isn't terribly relevant for a simple example that tries to illustrate a common coding technique - not withstanding my poorly placed increment which i apologise for and have now corrected.
If you are suggesting i should use a different variable for iterating the string, then yes that would be better, but i felt adding more variables would not add anything. But if that is what is required then it could be written as
char *str = "hello";
char *p = str;
while (*p) {
// do something with *p for example
Serial.println (*p);
}
I never said that a pointer could point to a single bit.
You said a bool could be stored in a single bit.
OK a little clarification although I think the question has been sorta answered by Delta_G. (post #6)
const bool pin = 2;
void setup()
{
pinMode(pin, OUTPUT);
}
void loop()
{
digitalWrite(pin, HIGH);
delay(1000);
digitalWrite(pin,LOW);
delay(1000);
}
a few misspellings on my part may have confused the issue a bit. I understand that boolean is true or false. The idea behind it was, in a digital only application where the output would only ever be HIGH or LOW then the boolean operator 'should' be able to do this. If this is not done...it is not done. it was just something I was wool gathering about if it was possible or something that was done when space got tight inside of and Uno or smaller device. The actual real question is, if it is not done, why is it not done.
thank you for your insight
machinetech
This is still not correct language use, even though it compiles. Use an integer type for numbers. This use will produce an error and if intended then saying it like that is like not a native C++ speaker