lunedì 13 giugno 2011

Is “(uint16_t) -1″ Portable C Code?

Is “(uint16_t) -1″ Portable C Code?: "

Twice in the last month, Netrino’s engineers have run across third-party middleware that included a statement of the form:


uint16_t variable = (uint16_t) -1;


which we take as the author’s clever way of coding:


0xFFFF


We aren’t naturally inclined to like the obfuscation anyway, but also wondered if “(uint16_t) -1″ is even portable C code? And, supposing it is portable, is there some advantage we don’t know about that suggests using that form over the hex literal? In the process of researching these issues, I learned a helpful fact or two worth sharing.


Q: Is the result of “(uint16_t) -1″ guaranteed (by the ISO C standard) to be 0xFFFF?


A: No. But it’s likely the result will be 0xFFFF on most compilers/processors, since there is really just the one common internal CPU representation of unsigned integers. (For signed integers, most/all processors will use the common 2′s complement representation underneath–even though that’s not required in any way by the language standard.)


Q: Is there any advantage to writing 0xFFFF that way?


A: According to the C99 Standard, all conforming implementations support uint_least16_t, but some may not support uint16_t. If the platform doesn’t support uint16_t, then “(uint16_t) -1″ won’t compile, but 0xFFFF will compile as a value of some larger unsigned integer type (i.e., a bug waiting to happen).


Of course, platforms that don’t have a fixed-width 16-bit unsigned capability are rare, though it may be that some DSPs fall into that category. The same issue applies to uint32_t and 0xFFFFFFFF, of course. However, I suspect platforms that don’t have a fixed-width 32-bit unsigned capability are even rarer.


Q: What is the best way to represent the maximum unsigned integer value of a given size?


A: The very best way to represent the maximum values for unsigned (and signed) fixed-width types is to use the constants named in C99′s stdint.h header file. These are of the form UINTn_MAX (and INTn_MAX) where n is the number of bits (e.g., UINT16_MAX). That is guaranteed to either work or not compile, with no middle ground for bugs.


Hat Tip: Many thanks to C and C++ standards guru Dan Saks for help with these answers.

"

0 commenti:

Posta un commento

Nota. Solo i membri di questo blog possono postare un commento.