Hi All,
I have been trying to test a character string (read from a Nextion screen) that contains bytes containing hex 0xFF. When I put in a condition to test for it the condition was never evaluated to true. I did some experimenting, and found that the only value the 0xFF byte would return a value of true when compared for equality was 0xFFFFFFFF, That's four bytes of high values. Now I'm not sure what's happening. I knocked up a quick program to check a few things, and, to be honest, I'm still confused.
This is the program.
// unsigned short hiVal = 255;
short hiVal = 255;
unsigned long hiVals = 4294967295; // 2^32-1 is the highest value that can be stored in four bytes.
long hiValsPos = 2147483647; // 2^31-1 is highest signed integer four bytes can store
long hiValsNeg = -2147483648; // -(2^32) is lowest signed integer four bytes can store
short hiValU = -1; // should be 0xFF I think...
unsigned int hiVal2 = 65535;
char testChar = 0xFF;
void setup() {
Serial.begin(9600);
checkIt(hiVal, "hiVal");
checkIt(0xFF, "0xFF");
checkIt(0xff, "0xff");
checkIt(0xFFFF, "0xFFFF");
checkIt(0xffff, "0xffff");
checkIt(0xFFFFFF, "0xFFFFFF");
checkIt(0xFFFFFFFF, "0xFFFFFFFF");
checkIt(hiVals, "hiVals");
checkIt(hiValsPos, "hiValsPos");
checkIt(hiValsNeg, "hiValsNeg");
checkIt(hiValU, "hiValU");
checkIt(hiVal2, "hiVal2");
checkIt(-1, "minus one");
}
void loop() {
}
void checkIt(long testVal, String testValName) {
if (testChar == testVal) {
Serial.print(" Val: " + String(testValName) + " worked ");
} else {
Serial.print(" Val: " + String(testValName) + " DID NOT MATCH ");
}
Serial.println(testValName + " = " + String(testVal, DEC) + " HEX " + String(testVal,HEX) + " (" + sizeof(testVal) + ")");
}
This is the output it produces.
Val: hiVal DID NOT MATCH hiVal = 255 HEX ff (4)
Val: 0xFF DID NOT MATCH 0xFF = 255 HEX ff (4)
Val: 0xff DID NOT MATCH 0xff = 255 HEX ff (4)
Val: 0xFFFF DID NOT MATCH 0xFFFF = 65535 HEX ffff (4)
Val: 0xffff DID NOT MATCH 0xffff = 65535 HEX ffff (4)
Val: 0xFFFFFF DID NOT MATCH 0xFFFFFF = 16777215 HEX ffffff (4)
Val: 0xFFFFFFFF worked 0xFFFFFFFF = -1 HEX ffffffff (4)
Val: hiVals worked hiVals = -1 HEX ffffffff (4)
Val: hiValsPos DID NOT MATCH hiValsPos = 2147483647 HEX 7fffffff (4)
Val: hiValsNeg DID NOT MATCH hiValsNeg = -2147483648 HEX 80000000 (4)
Val: hiValU worked hiValU = -1 HEX ffffffff (4)
Val: hiVal2 DID NOT MATCH hiVal2 = 65535 HEX ffff (4)
Val: minus one worked minus one = -1 HEX ffffffff (4)
It seems to confirm that to test for a single byte containing 0xFF, it is necessary to compare it to a four byte variable containing 0xFFFFFFFF.
Am I missing something basic here?
All advice gratefully received.
to test for a single byte containing 0xFF
But you are not using a byte, you are using a char
Have you tried printing testChar or declaring it unsigned ?
Let us review the basics:
1. What is the significance of the keyword byte in the following declaration/codes:
byte x = 0x41; //x holds: 0100 0001
Serial.print(x, DEC); //shows: 65
2. What is the significance of the keyword char in the following declaration/codes:
char x = 0x41; //x holds: 0100 0001
Serial.print(x); //shows: A
3. What is the significance of the keyword char in the following declaration/codes:
char x = 0x41; //x holds: 0100 0001
Serial.print(x, DEC); //shows: 65
What understanding we can infer from the above three examples?
Thanks for the quick responses.
My confusion is not so much how the content of a byte is represented. Clearly it can be used for different purposes depending on the requirements. If you need it to contain an ASCII character, then it can be used as a character, if a number then it can be used as a number, if you are interested in the hex value then that is how it is used and manipulated. I am familiar with this concept. That is not the issue I have.
The issue I have I thought I had stated clearly in the last sentence of my post, but perhaps it was a little vague. It is this. In order to test for a single byte (and I am using the term in it's literal sense as a set of eight bits, not as a variable type) containing 0xFF (or binary 11111111, or unsigned decimal 255, or signed decimal -1, they are all the same) I must compare it to a four byte string, with all 32 bits set to 1.
When hexChar is set to 0xFF as it is in my test program and never modified, why does the expression "if (hexChar == 0xFF)" evaluate to false? Why does the expression "if (hexChar == 0xFFFFFFFF)" evaluate to true?
Not only that, if a byte (again in the literal sense, regardless of the type it was defined as) with the high order bit set (i.e. has a hex value between 0x80 and 0xFF) is printed using the "HEX" parameter of the print command, it is displayed as if it were four bytes, not one. It is worth noting that in this case the length of the string being printed is correctly identified as 1.
I hope I have clarified the issue, and apologies for any misunderstanding.
If you want to test for a byte, why do you put the value into a char?
both datatypes are 8 bit wide, but chars are signed, bytes are not.
So, if the leftmost bit is set (like in 0xFF) the value will be extended with 0xFF when needed.
@whandall thank you for your answer. I changed the declaration of hexChar to byte, and now the compare to 0xFF evaluates to true. I am unclear however on why this should be, and I don't understand you comment that the value (of a char?) will be extended when needed. Is there documentation that explains that behaviour?
Thanks.
One more question though. I receive a string from my Nextion screen, which is a normal C String. If I try to use the data as is each character is treated as a char, not a byte. Is there an easy way to convert a char string to a byte array? I've done it in a for loop, but that seems a bit messy to me.
Thanks.
Well I learn something new every day.
Ian
In English Language perspective, the word image has two meanings: 'a picture of a scene taken by a camera' and 'personality'.
Likewise in Programming Language perspective, the word byte has two meanings: '8-bit' and 'data type'. For example:
8-bit expansion of 0xFF is: 11111111.
What is about byte data type?
Let us remember the doctrine that the meaning of a numerical figure/number is only known to the user. So, what is the value of 0xFF to you? Is it 255 or -1 or 'cc-code for 8.'? The user must tell it to himself before he puts this number to a machine/computer for processing.
Say, 0xFF bears the meaning of 255 which means that all the bits carry positive positional values:
0xFF
==> 11111111
==> 1x27 + 1x26+...+1x20
==> 255
We want to store the number 0xFF (255) into a computer memory location under the condition that the MCU will treat the content of the said location as an unsigned number during processing. This is ensured with the following declaration:
byte x = 0xFF;
Now, do the comparison and observe that the MCU has correctly taken 0xFF as 255.
void setup()
{
Serial.begin(9600);
byte x = 0xFF;
if(x == 0xFF)
{
Serial.print("true"); //correctly shows: true
}
}
void loop()
{
}
@GolamMostafa, thank you for your explanation. However @Whandall has already pointed out my mistake, I was using "char" type instead of "byte" type, as I thought they were essentially the same thing, a single byte. However as Whandall pointed out "char" type is treated as signed, "byte" type is treated as unsigned. So when I was trying to use 0xFF (or indeed any value greater than 0x80) in a char the system uses sign extension to maintain the correct sign, and increased the number of bytes used to manage the "char" variable. The documentation says that, while a "char" type is at least 8 bits (i.e. one byte) it can be up to four bytes. That's what tripped me up.
The keyword char is primarily designed to hold the ASCII codes for the characters of the English Language Alphabet Set. If someone wants to use it to store 'pure/abstract numerical' number -- that is the bad use of the keyword (from my point of view).
@GolamMostafa you are correct of course. However there are many languages that require a lot more than 255 characters, like Russian, Hindi, Malaylam, and of course Chinese and Japanese, just to name a few off the top of my head. So to accommodate these languages the definition of "char", it seems, had to be considerably expanded. Since I'm an English speaker I have no experience of programming in other languages, so it's never been a problem for me.
