![]() |
![]() |
| |||||||||||||||
Check UnionsBe sure to check unions because their fields might have changed sizes between ILP32 and LP64. For example,
should be:
Specify Constant TypesA loss of data can occur in some constant expressions because of lack of precision. These types of problems are very hard to find. Be explicit about specifying the type(s) in your constant expressions. Add some combination of {u,U,l,L} to the end of each integer constant to specify its type. You might also use casts to specify the type of a constant expression. For example,
should be:
Beware of Implicit DeclarationThe C compiler from Sun WorkShop assumes a type int for any function or variable that is used in a module and not defined or declared externally. Any longs and pointers used in this way are truncated by the compiler's implicit int declaration. The appropriate extern declaration for a function or variable should be placed in a header and not in the C module. The header should then be included by any C module that uses the function or variable. In the case of a function or variable defined by the system headers, the proper header should still be included in the code. For example, because getlogin() is not declared, the following code:
produces the warnings:
For better results, use::
sizeof Is an unsigned longIn LP64, sizeof has the effective type of an unsigned long. Occasionally, sizeof is passed to a function expecting an argument of type int, or is assigned or cast to an int. In some cases, this truncation might cause loss of data. For example,
produces the warnings:
Use Casts to Show Your IntentionsRelational expressions can be tricky because of conversion rules. You should be very explicit about how you want the expression to be evaluated by adding casts wherever necessary. Check Format String Conversion OperationThe format strings for printf(3C), sprintf(3C), scanf(3C), and sscanf(3C) might need to be changed for long or pointer arguments. For pointer arguments, the conversion operation given in the format string should be %p to work in both the 32-bit and 64-bit environments. For example,
produces the warning:
Use the following code to produce clean results:
For long arguments, the long size specification, l, should be prepended to the conversion operation character in the format string. Furthermore, check to be sure that the storage pointed to by buf is large enough to contain 16 digits. For example,
produces the warnings:
The following code will produce clean results:
Other ConsiderationsThe remaining guidelines highlight common problems encountered when converting an application to a full 64-bit program. Derived Types That Have Grown in SizeA number of derived types have changed so they represent 64-bit quantities in the 64-bit application environment. This change does not affect 32-bit applications; however, any 64-bit applications that consume or export data described by these types need to be reevaluated for correctness. An example of this is in applications that directly manipulate the utmpx(4) files. For correct operation in the 64-bit application environment, you should not attempt to directly access these files. Instead, you should use the getutxent(3C) and related family of functions. A list of changed derived types is included in Appendix A, Changes in Derived Types. Check for Side Effects of ChangesOne problem to be aware of is that a type change in one area might result in an unexpected 64-bit conversion in another area. For example, in the case of a function that previously returned an int and now returns an ssize_t, all the callers need to be checked. Check Whether Literal Uses of long Still Make SenseBecause a long is 32 bits in the ILP32 model and 64 bits in the LP64 model, there might be cases where what was previously defined as a long is neither appropriate nor necessary. In this case, it might be possible to use a more portable derived type. Related to this, a number of derived types might have changed under the LP64 data model for the reason stated above. For example, pid_t remains a long in the 32-bit environment, but under the 64-bit environment, a pid_t is an int. For a list of derived types modified for the LP64 compilation environment, see Appendix A, Changes in Derived Types. Use #ifdef for Explicit 32-bit Versus 64-bit PrototypesIn some cases, specific 32-bit and 64-bit versions of an interface are unavoidable. In the headers, these would be distinguishable by the use of the _LP64 or _ILP32 feature test macros. Similarly, code that is to work in 32-bit and 64-bit environments might also need to utilize the appropriate #ifdefs, depending on the compilation mode. Calling Convention ChangesWhen passing structures by value for SPARC V9, if the structure is small enough, it is passed in registers rather than as a pointer to a copy. This can cause problems when passing structures between C code and hand-written assembly code. Floating point parameters work in a similar fashion; some floating point arguments passed by value are passed in floating point registers. Algorithmic ChangesAfter code has been made 64-bit safe, review it again to verify that the algorithms and data structures still make sense. The data types are larger, so data structures might use more space. The performance of your code might change as well. Given these concerns, you might need to adapt your code appropriately. | |||||||||||||||
| |||||||||||||||