The only danger obvious in your code is sprintf (). The world would be a better place if no one had ever used it again. Replace it
void loop() { ... char buf[128]; sprintf(buf, "Integer-only reading: Temperature %hi.%01hi C, Humidity %i.%01i %% RH", myDHT22.getTemperatureCInt()/10, abs(myDHT22.getTemperatureCInt()%10), myDHT22.getHumidityInt()/10, myDHT22.getHumidityInt()%10); //Serial.println(buf);
with
void loop() { ... const size_t sizeBuf = 128; char szBuf[128+1]; snprintf(szBuf, sizeBuf, "Integer......", ... ); szBuf[sizeBuf] = '\0';
"n" versions exist for all string functions, and all of them provide a specification for the size of the destination buffer so you can be sure that they will never overflow the buffer. Note that functions do not provide null termination, so an extra line should guarantee.
So, with snprintf, you can be safe if, with an error of 1 million data errors, some unexpected string conversion occurs, your code will work.
Along this line, there is not much benefit to highlighting char buf [] inside the loop. Since the entire program executes the execution loop () endlessly, you are not saving memory resources by making this local variable on the stack. There is only a microscopic window in which the stack memory is not used. But while on the stack, if you overflow buf, overflow can erase the return address, which will undoubtedly lead to a program crash. These are all dangers without a return.
Think like that
const size_t sizeBuf = 128; char szBuf[128+1]; void loop() { ... snprintf(szBuf, sizeBuf, "Integer......", ... ); szBuf[sizeBuf] = '\0';
In this method, memory is allocated statically, and at compile time you know how much memory your program needs.