361 | | This instructs GCC to consider the release version of C or C++ and to first issue all warnings required by that version of the standard, and second warn about the use of gcc extenstions to the language. This would, for instance warn about the use of ''#ident'' since it is a gcc extension and is not in any of the standards. Using -pedantic makes it easier to write portable code, or at least to know when it is not. Best used with the ''-std=xxxxx'' argument to the compiler, so that you know what version of the standard you're being compared to. Currently if ''-std=xxxxx'' is not specified, it's as if you'd written ''-std=gnu++98''. Much of boost uses facilities from more recent versions of the standard, so it might make more sense to explicitly specify ''-std=c++0x'' or ''-std=gnu++0x''. ''-std=c++0x'' is most portable. See the page [http://gcc.gnu.org/onlinedocs/gcc/Standards.html] for more information. |
| 361 | This instructs GCC to consider the release version of C or C++ and to first issue all warnings required by that version of the standard, and second warn about the use of gcc extensions to the language. This would, for instance warn about the use of ''#ident'' since it is a gcc extension and is not in any of the standards. Using -pedantic makes it easier to write portable code, or at least to know when it is not. Best used with the ''-std=xxxxx'' argument to the compiler, so that you know what version of the standard you're being compared to. Currently if ''-std=xxxxx'' is not specified, it's as if you'd written ''-std=gnu++98''. Much of boost uses facilities from more recent versions of the standard, so it might make more sense to explicitly specify ''-std=c++0x'' or ''-std=gnu++0x''. ''-std=c++0x'' is most portable. See the page [http://gcc.gnu.org/onlinedocs/gcc/Standards.html] for more information. |
614 | | Scary, isn't it? Of course you could use -fno-strict-aliasing to get the right output, but the generated code won't be as good. A better way to accomplish the same thing without the warning's or the incorrect output is to define swaphalves like this: |
| 619 | Scary, isn't it? Of course, if you are using gcc, you could use -fno-strict-aliasing to get the right output, |
| 620 | but the generated code won't be as good. A better way to accomplish the same thing without the |
| 621 | warnings or the incorrect output is to define swaphalves like this. N.B. this is supported in C99 and |
| 622 | later C specs, as noted in this footnote to 6.5.2.3 Structure and union members:[[BR]] |
| 623 | {{{ |
| 624 | 85) |
| 625 | If the member used to access the contents of a union object is not the |
| 626 | same as the member last used to store a value in the object, the appropriate |
| 627 | part of the object representation of the value is reinterpreted as an object |
| 628 | representation in the new type as described in 6.2.6 (a process sometimes |
| 629 | called ‘‘type punning’’). This might be a trap representation. |
| 630 | }}} |
| 631 | but your mileage may vary in C++, almost all compilers support it, but the spec doesn't allow it. Right |
| 632 | after this discussion I'll have another solution with memcpy that may be slightly less efficient, (but |
| 633 | probably not), and is supported by both C and C++): |
| 634 | |
| 635 | ==== Union version. Fixed for C but not guaranteed portable to C++ ==== |
642 | | |
| 664 | So do it wrong, via strange casts and get incorrect code, or by turning off strict-aliasing get inefficient code, or do it right and get efficient code. |
| 665 | |
| 666 | You can also accomplish the same thing by using memcpy with char* to move the data around for the swap, and it will probably be as efficient. Wait, you ask me, how can that be? The will be at least to calls to memcpy added to the mix! Well gcc and other modern compilers have smart optimizers and will, in many cases, (including this one), elide the calls to memcpy. That makes it the most portable, and as efficient as any other method. Here's how it would look: |
| 667 | |
| 668 | ==== memcpy version, compliant to C and C++ specs and efficient ==== |
| 669 | |
| 670 | {{{ |
| 671 | uint32_t |
| 672 | swaphalves(uint32_t a) |
| 673 | { |
| 674 | uint16_t as16bit[2],tmp; |
| 675 | |
| 676 | memcpy(as16bit, &a, sizeof(a)); |
| 677 | tmp = as16bit[0]; |
| 678 | as16bit[0] = as16bit[1]; |
| 679 | as16bit[1] = tmp; |
| 680 | memcpy(&a, as16bit, sizeof(a)); |
| 681 | return a; |
| 682 | } |
| 683 | }}} |
| 684 | For the above code, a C compiler will generate code similar to the previous solution, but with the addition of two calls to memcpy (possibly optimized out). gcc generates code identical to the previous solution. You can imagine other variants that substitute reading and writing through a char pointer locally for the calls to memcpy. |