#include <SoftwareSerial.h>
//SoftwareSerial USB_HOST_SERIAL = SoftwareSerial(2, 3); // RX, TX
void setup() {
Serial.begin(115200);
delay(100);
}
void loop() {// put your main code here, to run repeatedly:
unsigned long int k = 512 * 1024;
//unsigned long int k = 524288;
Serial.println(k);
delay(100);
}
It was expected to be displayed 524288 in serial monitor.
However, what I got is 0 like below.
It would be helpful if you tell me which portion is wrong in my code.
〇My environment
Arduino IDE 1.8.15 + Arduino Uno R3
This problem was observed with Arduino Pro Miro 3.3V 8MHz also.
Thank you for your response.
I tried that, but the result was the same.
#include <SoftwareSerial.h>
//SoftwareSerial USB_HOST_SERIAL = SoftwareSerial(2, 3); // RX, TX
void setup() {
Serial.begin(115200);
delay(100);
}
void loop() {// put your main code here, to run repeatedly:
unsigned long k = 512 * 1024;
//unsigned long int k = 524288;
Serial.println(k);
delay(100);
}
512 and 1024 are both less than 32767 so they are both treated as 'int'. The multiply causes an integer overflow leaving a result of 0. That 0 is then converted to 'unsigned long int'.
To have the math done in unsigned long int, use unsigned long int constants: unsigned long int k = 512ul * 1024ul;
Note: The arguments to the multiply will have the 'usual conversions' applied. You only need one of the two to be 'unsigned long int' for the other to be converted to 'unsigned long int' before the multiply.
By default, an integer constant is treated as an int with the attendant limitations in values. To specify an integer constant with another data type, follow it with:
a 'u' or 'U' to force the constant into an unsigned data format. Example: 33u
a 'l' or 'L' to force the constant into a long data format. Example: 100000L
a 'ul' or 'UL' to force the constant into an unsigned long constant. Example: 32767u
Casting is useful for variables. For constants, it makes more sense to use the right type of constant rather than casting the wrong type to the right type.
I expect most of the versions that produce the right answer will end up compiling to the same code. The compiler is smart enough to do the conversions and the math so, in the binary, everything will look the same as: k = 524288;
That doesn't mean you should use "k = 524288" in your code because people reading the code will have a hard time figuring out why you are using that value. Good programming practice would be for the 1024 constant to have a useful name and the 512 constant to have a useful name.
actually when you have a long and an int, the int is promoted first into the larger storage (so long in that case), the multiplication is done using long, and then the result is transformed (with very clear rules) into the destination type of your variable.
Also important to know that
if one of the operand is unsigned and the other is signed, then the later is transformed in place into the equivalent memory representation as unsigned (ie the bits are interpreted as if the value was unsigned) for the operation.
if you store an unsigned value into a signed value, the bits are interpreted directly.
if the operant fit on a byte, it is transformed into the (signed/unsigned) int (bit equivalent) representation before doing the math.
that leads to interesting results if you are not careful. For example, on a UNO this code