![]() |
![]() |
| |||||||||||||
Guidelines for Converting to LP64When using lint(1), remember that not all problems result in lint(1) warnings, nor do all lint(1) warnings indicate that a change is required. Examine each possibility for intent. The examples that follow illustrate some of the more common problems you are likely to encounter when converting code. Where appropriate, the corresponding lint(1) warnings are shown. Do Not Assume int and Pointers Are the Same SizeSince ints and pointers are the same size in the ILP32 environment, a lot of code relies on this assumption. Pointers are often cast to int or unsigned int for address arithmetic. Instead, pointers could be cast to long because long and pointers are the same size in both ILP32 and LP64 worlds. Rather than explicitly using unsigned long, use uintptr_t because it expresses the intent more closely and makes the code more portable, insulating it against future changes. For example,
produces the warning:
Using the following code will produce the clean results:
Do Not Assume int and long Are the Same SizeBecause ints and longs were never really distinguished in ILP32, a lot of existing code uses them indiscriminately while implicitly or explicitly assuming that they are interchangeable. Any code that makes this assumption must be changed to work for both ILP32 and LP64. While an int and a long are both 32-bits in the ILP32 data model, in the LP64 data model, a long is 64-bits. For example,
produces the warning:
Sign ExtensionSign extension is a common problem when converting to 64-bits. It is hard to detect before the problem actually occurs because lint(1) does not warn you about it. Furthermore, the type conversion and promotion rules are somewhat obscure. To fix sign extension problems, you must use explicit casting to achieve the intended results. To understand why sign extension occurs, it helps to understand the conversion rules for ANSI C. The conversion rules that seem to cause the most sign extension problems between 32-bit and 64-bit integral values are:
For a more detailed discussion of the conversion rules, refer to the ANSI C standard. Also included in this standard are useful rules for ordinary arithmetic conversions and integer constants. When compiled as a 64-bit program, the addr variable in the following example becomes sign-extended, even though both addr and a.base are unsigned types. Example 4-1 test.c
This sign extension occurs because the conversion rules are applied as follows:
When this same example is compiled as a 32-bit program it does not display any sign extension:
Use Pointer Arithmetic Instead of Address ArithmeticIn general, using pointer arithmetic works better than address arithmetic because pointer arithmetic is independent of the data model, whereas address arithmetic might not be. It usually leads to simpler code as well. For example,
produces the warning:
The following code will produce clean results:
Repack StructuresExtra padding may be added to a structure by the compiler to meet alignment requirements as long and pointer fields grow to 64 bits for LP64. In the 64-bit environment on SPARC platforms, all types of structures are aligned to at least the size of the largest quantity within them. A simple rule for repacking a structure is to move the long and pointer fields to the beginning of the structure and rearrange the rest of the fields--usually, but not always, in descending order of size, depending on how well they can be packed. For example,
For better results, use:
| |||||||||||||
| |||||||||||||