Kingofark's INEFFECTIVE CC ++: Self-White 2: Sign, no symbol, there is an operation, my day!

zhaozj2021-02-08  392

INEFFECTIVE C / C : The Confession of A Novel "ineffective C / C : a low white"

BY K] [N g of @ r k

[Declaration: Kingofark is not a master, and the examples raised in the discussion may not be available, and it is not necessarily a good practice. All examples are merely illustrative and are not representative. Kingofark self-love is shallow, welcome to propose criticism and pointed out the mistake. ]

Item 2: Signed and Unsigned and Bit Operation, Oh my! Self-White 2: Sign, no symbol, there is a bit of operation, my day!

[Question]: Is this function of this function?

// ** * This function connects the value of two 16-bit albts into a value of a 32-bit. * Parameters: shighbits High 16-bit * Slowbits low 16-bit * Back: 32-bit value ** / long catenateBits16 (Short Shighbits, Short Slowbits) {long LRESULT = 0; / * 32-bit Temporary Variables * / / * A 16-bit value is placed in a 32-bit value of 16-bit * / LRESULT = shighbits; LRESULT = ShighBits; LRESULT << = 16; / * Clear 32-bit value low 16-bit * / LRESULT & = 0xffff0000; / * will be the second 16 The bit value is placed in a 32-bit value of 16-bit * / LRESULT | = (long) Slowbits; Return LRESULT;} /

[Discovery]:

Let's first see the following test code:

/ Int main () {short sHighBits1 = 0x7fff; short sHighBits2 = 0x8f12; unsigned short usHighBits3 = 0xff12; short sLowBits1 = 0x7bcd; long lResult = 0; printf ( "[sHighBits1 sLowBits1] / n"); lResult = CatenateBits16 (sHighBits1 , sLowBits1); printf ( "lResult =% 08x / n", lResult, lResult); lResult = CatenateBits16 (sHighBits2, sLowBits1); printf ( "lResult =% 08x / n", lResult, lResult); lResult = CatenateBits16 (usHighBits3 , Slowbits1); Printf ("LRESULT =% 08x / N", LRESULT, LRESULT);} /

The result of the operation is:

[shighbits1 slowbits1] LRESULT = 7FFF7BCDLRESULT = 8f127bcdlResult = ff127bcd

Well, it's very correct ... so we are safe to use this function in your own procedure.

But suddenly one day, one of our procedures is wrong in any case! After n hour's inspection and debugging, finally finally tracked into ... catenatebits16 ()! ? Its return value is actually wrong! ! "Depressed!" You said, "How can this function have a problem !?"

However, more depressed is still behind, because you use the input of the program as a parameter, in a simple main () single step debugging:

/ Int main () {short sHighBits1 = 0x7FFF; short sHighBits2 = 0x8F12; unsigned short usHighBits3 = 0x8F12; short sLowBits1 = 0x7BCD; // you are actually using the parameters short sLowBits2 = 0x8BCD; // long lResult parameter = 0 you are actually using ; printf ( "[sHighBits1 sLowBits1] / n"); lResult = CatenateBits16 (sHighBits1, sLowBits1); printf ( "lResult =% 08x / n", lResult, lResult); lResult = CatenateBits16 (sHighBits2, sLowBits1); printf ( "LRESULT, LRESULT", LRESULT, LRESULT); LRESULT = CATENATEBITS16 (UshighBits3, Slowbits1); Printf ("LRESULT =% 08X / N", LRESULT, LRESULT); Printf ("/ N [ShighBits1 Slowbits2] / N "); LRESULT = catenateBits16 (shighbits1, slowbits2); Printf (" LRESULT =% 08X / N ", LRESULT, LRESULT); LRESULT = CatenateBits16 (Shighbits22, Slowbits2); Printf (" LRESULT =% 08x / N ", LRESULT , LRESULT); LRESULT = catenateBits16 (UshighBits3, Slowbits2); Printf ("LRESULT =% 08x / N", LRESULT, LR Esult); Return 0;} /

The findings were actually:

[shighbits1 slowbits1] LRESULT = 7FFF7BCDLRESULT = 8f127bcdlResult = 8f127bcd

[shighbits1 slowbits2] LRESULT = fff8bcd // OOPS! LRESULT = fff8bcd // OOPS! LRESULT = FFFF8BCD // OOPS!

The last time is still good, I will ffff in one time? X Archive?

[The truth of the arch file]: Note the two we have used as a low 16-bit value of Slowbits1 and Slowbits2.

Known: When using Slowbits1 = 0x7bcd, the function returns the correct value; when using Slowbits2 = 0x8bcd, an X file is in the function.

So, what is the difference between Slowbits1 and Slowbits2?

Note that Slowbits1 and Slowbits2 are SHORT types (rather than unsigned short), so Slowbits1 represents a positive value, while SlowBits2 represents a negative value (because 8 is binary 1000, Slowbits2 is 1).

Look at the catenatebits16 () function:

/ Long catenateBits16 (Short SHIGHBITS, Short Slowbits) {long LRESULT = 0; / * 32-bit value temporary variable * / / * put the first 16-bit value into the 32-bit value of 16 bits * / LRESULT = shighbits; LRESULT << = 16; / * Clear 32-bit value low 16-bit * / LRESULT & = 0xffff0000; / * put the second 16-bit value into a 32-bit value of 16-bit * / LRESULT | = (long) Slowbits ; // pay attention to this! ! ! ! Return LRESULT;} /

If we use it in a function

Printf ("Slowbits =% 04x / N", Slowbits);

Print the incoming SlowBits value, will find

When Slowbits = 0x7bcd, the print result is

Slowbits = 7bcd

When Slowbits = 0x8bcd, the print result is

Slowbits = fff8bcd

Yes, that is, the 8-bit hexadecimal is printed using% 04x.

Therefore, we see:

When Slowbits = 0x8bcd, "LRESULT | = (long) Slowbits;" will be converted to SlowBITS first

0xffff8bcd

Also do or operate with LRESULT. Since the value of LRESULT is 0xxxxxxxx0000 (where xxxx is any value), it is obvious that the last result will be the value of shighbits.

0xffff8bcd

When Slowbits = 0x7bcd, "LRESULT | = (long) slowbits;" will be converted to

0x00007BCD

Also do or operate with LRESULT. The result of this or the operation is of course right.

That is, catenateBits16 () performs normal when Slowbits is 0, and the deviation occurs when the highest bit is 1.

[Lesson: In some cases operations and bit processing, consider using unsigned values ​​- because this time often does not need to handle symbols. Even if you need a symbolful value, you should also consider making your own conversion before and after calling catenateBits16 () - after all in the bit processing, there is a symbol value quite weird! ]

This catenateBits16 () version should be better:

/ unsigned long catenatebits16 (unsigned short sales bits) {long LRESULT = 0; / * Put the first 16-bit value into a 32-bit value of 16-bit * / LRESULT = shighbits; LRESULT << = 16; / * Clear 32-bit value low 16-bit * / LRESULT & = 0xffff0000; / * put the second 16-bit value into a 32-bit value low 16-bit * / LRESULT | = (long) SlowBITS & 0x0000FFFF; Return LRESULT;} / Note "LRESULT | = (long) Slowbits & 0x0000FFF;". In fact, even if we declare the parameters of the CatenateBits16 () function as a short, the result will also be correct.

[Kingofark's harvest]:

If you throw a rabbit to a tiger, the tiger eats the rabbit, and throws a mouse on the next day, it eats, then explains the first day you have a mistake: it is a one Cat.

转载请注明原文地址:https://www.9cbs.com/read-390.html

New Post(0)