A standard way to convert individual bytes to a number is to use bit
shifts and bitwise OR, as shown in chrisl's answer. When doing this,
however, one has to take care not to overflow the bit shifts. On the
AVR-based Arduinos, an int
is 16 bits long. Shifting it by
24 bit positions to the left is guaranteed to overflow, which in
C++ leads to undefined behavior.
The solution, as explained in Majenko's comment, is to cast to the final
type before shifting, like this:
uint32_t uid = (uint32_t) mfrc522.uid.uidByte[0] << 0
| (uint32_t) mfrc522.uid.uidByte[1] << 8
| (uint32_t) mfrc522.uid.uidByte[2] << 16
| (uint32_t) mfrc522.uid.uidByte[3] << 24;
Note that I got rid of the useless intermediate variables A
through
D
.
Once you have have the numerical value, you may try to use it without
explicitly converting to a string. Instead, you rely on the print()
or println()
methods to implicitly do the conversion only when needed,
as in
Serial.print("UID = ");
Serial.println(uid);
or even, on a network connection:
client.print(uid);
This will save you the memory needed to store the string. If you really
need to have the converted string in memory, which could happen if you
need to provide a Content-Length before sending the data, you can do so
with the function ultoa()
from the avr-libc:
char uid_str[11]; // max = 10 digits + terminating NUL
ultoa(uid, uid_str, 10); // convert to base 10
Please note that ltoa()
is not appropriate here, as calling it
will implicitly convert the value to a signed long
, which has the
potential to overflow and yield a negative result.
This “C string” – a NUL-terminated character array – can then
be converted to a String object if needed, but I advice you against doing so
if at all possible. String objects are more convenient to manipulate,
but they are absolutely not memory friendly, which can quickly become an
issue on most Arduinos.