From: <ad...@ne...> - 2005-10-19 09:35:29
|
/** * Calculates the updated value of a checksum. The values are 4 bytes. * * @param uOrigSum the original checksum * @param uOldValue a long value to subtract * @param uNewValue a long value to add * @return the updated checksum */ inline u_short in_cksum_replace_long(u_short uOrigSum, u_long uOldValue, u_long uNewValue) { u_long uSum = uOrigSum; #if 1 uSum += *((u_short*)&uOldValue) + (~(*((u_short*)&uNewValue)) & 0xFFFF) + *((u_short*)&uOldValue + 1) + (~(*((u_short*)&uNewValue + 1)) & 0xFFFF); #else uNewValue = ~uNewValue; uSum += (uOldValue & 0xFFFF) + (uOldValue >> 16); uSum += (uNewValue & 0xFFFF) + (uNewValue >> 16); #endif uSum = (uSum >> 16) + (uSum & 0xFFFF); uSum += (uSum >> 16); return uSum; } The above function updates the checksum in a packet. The two alternatives should be identical in functionality, but the active version cannot give reliable results when -O2 is used with GCC 3.4.4. Attached is a complete test case (the last two lines of output should be identical). Compiling with 3.2 or 2.95.3 is OK. Removing `inline' will remove the wrong behaviour. Even commenting out one `cout << sum << endl;' will make the problem disappear! Does anyone know whether it is a known bug of GCC 3.4 (regarding inlining and addressof)? Best regards, Yongwei |