Guidelines for Specific Scenarios

This chapter lists an assortment of scenarios that relate to a specific technology or API. Although many of these scenarios are uncommon, you will want to at least glance at the topics to determine whether anything applies to your application. The topics are organized alphabetically.


Aliases are big-endian on all systems. Applications that add extra information to the end of an AliasHandle must ensure that the extra data is always endian-neutral or of a defined endian type, preferably big-endian.

The AliasRecord data structure is opaque when building your application with the Mac OS X v10.4(Universal) SDK. Code that formerly accessed the userType field of an AliasRecord must use the Alias Manager functions GetAliasUserType, GetAliasUserTypeFromPtr, SetAliasUserType, or SetAliasUserTypeFromPtr. Code that formerly accessed the aliasSize field of an AliasRecord must use the functions GetAliasSize or GetAliasSizeFromPtr.

These Alias Manger functions are available in Mac OS X v10.4 and later. For more information, see Alias Manager Reference.

Archived Bit Fields

For cross platform portability, avoid using bit fields. It’s best not to use the NSArchiver class to archive any structures that contain bit fields as integers. Individual values are stored in the archives in an architecture and compiler dependent manner. In cases where archives already contain such structures, you can read a structure correctly by changing its declaration so that the bit fields are swapped appropriately

Automator Scripts

AppleScript actions are platform-independent and do not need any changes to run on Intel-based Macintosh computers. However, any action that contains Cocoa code, whether it is a solely Cocoa action or an action that uses both AppleScript and Cocoa code, must be built as a universal binary to run correctly on both architectures.

For more information, see Automator Programming Guide.

Bit Shifting

When you shift a value by the width of its type or more, the fill bits are undefined regardless of the architecture. In fact, two different compilers on the same architecture could differ on the value of y after these two statements:

uint32_t x = 0xDEADBEEF;

uint32_t y = x >> 32;

Bit Test, Set, and Clear Functions: Carbon and POSIX

Don’t mix using the C bitwise operators with the Carbon functions BitTst, BitSet, and BitClr and the POSIX macros setbit, clrbit, isset, and isclr. If you consistently use the Carbon and POSIX functions and avoid the C bitwise operators, your code will function properly. Keep in mind, however, that you must use the Carbon and POSIX functions on the correct kind of data. The Carbon and POSIX functions perform a byte-by-byte traversal, which causes problems on an Intel-based Macintosh when they operate on data types that are larger than 1 byte. You can use these functions only on a pointer to a string of endian-neutral bytes. When you need to perform bit manipulation on integer values you should use functions such as (int32 & (1 << 26)) instead of BitTst(&int32, 5L).

You’ll encounter problems when you use the function BitTst to test for 24-bit mode. For example, the following bit test returns false, which indicates that the process is running in 24-bit mode, or at least that the code is not running in 32-bit mode. The POSIX equivalents perform similarly:

Gestalt(gestaltAddressingModeAttr, &gestaltResult);
if (!(BitTst(&gestaltResult,31L)) )      /*If 24 bit

You can use any of the bit testing, setting, and clearing functions if you pass a pointer to data whose byte order is fixed. Used in this way, these functions behave the same on both architectures.

For more information, see the ToolUtils.h header file in the Core Services framework and Mathematical and Logical Utilities Reference.

CPU Subtype

Don't try to build a binary for a specific CPU subtype. Since the CPU subtype for Intel-based Macintosh computers is generic, you can't use it to check for specific functionality. If your application requires information about specific CPU functionality, use the sysctlbyname function, providing an appropriate selector. See Mac OS X Man Pages for information on using sysctlbyname.

Dashboard Widgets

Dashboard widgets typically contain platform-independent elements such as HTML, JavaScript, CSS, and image files. If you create a widget that contains only these elements, it should work on both PowerPC and Intel-based Macintosh computers without any modification on your part. However, if your widget contains a plug-in, you must build the plug-in as a universal binary for it to run natively on an Intel-based Macintosh computer.

For more information, see Dashboard Programming Topics.

Deprecated Functions

Many deprecated functions, such as those that use PICT + PS data, have byte swapping issues. You may want to replace deprecated functions at the same time you prepare your code to run as a universal binary. You’ll not only solve byte swapping issues, but your code will use functions that ultimately benefit future development.

A function that is deprecated has an availability statement in its header file that states the version of Mac OS X in which the function is deprecated. Many API reference documents provide a list of deprecated functions. In addition, compiler warnings for deprecated functions are on by default in Xcode 2.2 and later.

Disk Partitions

The standard disk partition format on an Intel-based Macintosh computer differs from the disk partition format of a PowerPC-based Macintosh computer. If your application depends on the partitioning details of the disk, it may not behave as expected. Partitioning details can affect tools that examine the hard disk at a low level.

By default, internal hard drives on Intel-based Macintosh computers use the GUID Partition Table (GPT) scheme and external drives use the Apple Partition Map (APM) partition scheme. To create an external USB or FireWire disk that can boot an Intel-based Macintosh computer, select the GPT disk partition scheme option using Apple Disk Utility. Starting up an Intel-based Macintosh using an APM disk is not supported.

Double-Precision Values: Bit-by-Bit Sensitivity

Although both architectures are IEEE 754 compliant, there are differences in the rounding procedure used by each when operating on double-precision numbers. If your application is sensitive to bit-by-bit values in double-precision numbers, be aware that the same computation performed on each architecture may produce a different numerical result.

For more information, see Volume 1 of the Intel developer software manuals, available from the following website:

Finder Information and Low-Level File System Operations

If your code operates on the file system at a low level and handles Finder information, keep in mind that the file system does not swap bytes for the following information:

The value of multibyte fields on disk always uses big-endian format. When running on a little-endian system, you must swap the bytes of any multibyte fields.

The getattrlist function retrieves the metadata associated with a file. The getxattr function, added in Mac OS X v10.4, retrieves extended attributes—those that are an extension of the basic set of attributes. When using the getxattr function to access the legacy attribute "", note that as with getattrlist, the information returned by this call is not byte swapped. (For more information on the getxattr and getattrlist functions see Mac OS X Man Pages.)

FireWire Device Access

The FireWire bus uses big-endian format. If you are developing a universal binary version of an application that accesses a FireWire device, see “FireWire Device Access on an Intel-Based Macintosh” in FireWire Device Interface Guide for a discussion of the issues you can encounter.

Font-Related Resources

Font-related resource types (FOND, NFNT, sfnt, and so forth) are in big-endian format on both PowerPC and Intel-based Macintosh computers. If your application accesses font-related resource types directly, you must swap the fields of font-related resource types yourself.

The following functions from the ATS for Fonts API obtain font resources that are returned in big-endian format:

The following functions from the Font Manager API obtain font resources that are returned in big-endian format. Note that Font Manager API is based on QuickDraw technology, which was deprecated in Mac OS X v10.4.


When the QuickDraw function NewGWorld allocates storage for the pixel buffer, and the depth parameter is 16 or 32 bits, the byte ordering within each pixel matters. The pixelFormat field of the PixMap data structure can have the values k16BE555PixelFormat or k16LE555PixelFormat for 2-byte pixels, and k32ARGBPixelFormat or k32BGRAPixelFormat for 4-byte pixels. (These constants are defined in the Quickdraw.h header file.) By default, NewGWorld always creates big-endian pixel formats (k16BE555PixelFormat or k32ARGBPixelFormat), regardless of the endian format of the system.

For best performance, it is generally preferable for you to use a pixel format that corresponds to the native byte ordering of the system. When you pass kNativeEndianPixMap in the flags parameter to NewGWorld, the byte ordering of the pixel format is big-endian on big-endian systems, and little-endian on little-endian systems.

You can use the GWorld pixel storage as input to the Quartz function CGBitmapContextCreate or as a data provider for the Quartz function CGImageCreate. The byte ordering of the source pixel format needs to be communicated to Quartz through additional flags in the bitmapInfo parameter. These flags are defined in the CGImage.h header file. Assuming that your bitmapInfo parameter is already set up, you now need to combine it (by using a bitwise OR operator) with kCGBitmapByteOrder16Host or kCGBitmapByteOrder32Host if you created the GWorld with a kNativeEndianPixMap flag. Similarly, you should use kCGBitmapByteOrder16Big or kCGBitmapByteOrder32Big when you know that your pixel byte order is big-endian.

Java Applications

Pure Java applications do not require any code changes to run on Intel-based Macintosh computers. However, Java applications that interface with PowerPC-based native code will not run successfully using Rosetta on Intel-based Macintosh computers.

Specifically, the following must be built as universal binaries:

For more information, see Technical Q &A QA1295: Java on Intel-based Macintosh Computers in the ADC Reference Library.

Java I/O API (NIO)

The I/O API (NIO) that was introduced in JDK 1.4 allows the use of native memory buffers. If you are a Java programmer who uses this API, you may need to revise your code. NIO byte buffers have a byte ordering that by default is big-endian. If you have Java code originally written for Mac OS X on PowerPC, when you create java.nio.ByteBuffers you should call the function ByteBuffer.order(ByteOrder.nativeOrder()) to set the byte order of the buffers to the native byte order for the current architecture. If you fail to do this, you will obtain flipped data when you read multibyte data from the buffer using JNI.

Machine Location Data Structure

The Memory Management Utilities data type MachineLocation contains information about the geographical location of a computer. The ReadLocation and WriteLocation functions use the geographic location record to read and store the geographic location and time zone information in extended parameter RAM.

If your code uses the MachineLocation data structure, you need to change it to use the MachineLocation.u.dls.Delta field that was added to the structure in Mac OS X version 10.0.

To be endian-safe, change code that uses the old field:

MachineLocation.u.dlsDelta = 1;

to use the new field:

MachineLocation.u.dls.Delta = 1;

The gmtDelta field remains the same—the low 24 bits are used. The order of assignment is important. The following is incorrect because it overwrites results:

MachineLocation.u.dls.Delta = 0xAA;    // u = 0xAAGGGGGG; G=Garbage
MachineLocation.u.gmtDelta = 0xBBBBBB;   // u = 0x00BBBBBB;

This is the correct way to assign the values:

MachineLocation.u.gmtDelta = 0xBBBBBB;   // u = 0x00BBBBB;
MachineLocation.u.dls.Delta = 0xAA;       // u = 0xAABBBBBB;

For more details see Memory Management Utilities Reference.

Mach Processes: The Task for PID Function

The task_for_pid function returns the task associated with a process ID (PID). This function can be called only if the process is owned by the procmod group or if the caller is root.

Metrowerks PowerPlant

You can use PowerPlant on an Intel-based Macintosh computer by downloading the PowerPlant framework available from This Open Source version of the PowerPlant Framework for Mac OS X includes support for Intel and GCC 4.0.


Multithreading is a technique used to improve performance and enhance the perceived responsiveness of applications. On computers with one processor, this technique can allow a program to execute multiple pieces of code independently. On computers with more than one processor, multithreading can allow a program to execute multiple pieces of code simultaneously. If your application is single-threaded, consider threading your application to take advantage of hardware multithreading processor capabilities. If your application is multithreaded, you’ll want to ensure that the number of threads is not hard coded to a fixed number of processors.

Dual-core technology improves performance by providing two physical cores within a single physical processor package. Multiprocessor and dual-core technology all exploit thread-level parallelism to improve application and system responsiveness and to boost processor throughput.

When you prepare code to run as a universal binary, the multithreading capabilities of the microprocessor are transparent to you. This is true whether your application is threaded or not. However, you can optimize your code to take advantage of the specific way hardware multithreading is implemented for each architecture.

Objective-C: Messages to nil

In Objective-C, it is valid to send a message to a nil object. The Objective-C runtime assumes that the return value of a message sent to a nil object is nil, as long as the message returns an object or any integer scalar of size less than or equal to sizeof(void*).

On Intel-based Macintosh computers, messages to a nil object always return 0.0 for methods whose return type is float, double, long double, or long long. Methods whose return value is a struct, as defined by the Mac OS X ABI Function Call Guide to be returned in registers, will return 0.0 for every field in the data structure. Other struct data types will not be filled with zeros. This is also true under Rosetta. On PowerPC Macintosh computers, the behavior is undefined.

Objective-C Runtime: Sending Messages

The information in this section is only for developers who use the Objective-C runtime library, which is used primarily for developing bridge layers between Objective-C and other languages, or for low-level debugging. Most developers do not need to use the Objective-C runtime library directly when programming in Objective-C.

If your application directly calls the Objective-C runtime function objc_msgSend_stret, you need to change your code to have it work correctly on an Intel-based Macintosh.

The x86 ABI for struct-return functions differs from the ABI for struct-address-as-first-parameter functions, but the two ABIs are identical on PowerPC. When you call objc_msgSend_stret, you must cast the function to a function pointer type that uses the expected struct return type. The same applies for calls to objc_msgSendSuper_stret.

For other details on the ABI, see “32-Bit Application Binary Interface.”

If your application directly calls the Objective-C runtime function objc_msgSend, you should always cast to the appropriate return value. For instance, for a method that returns a BOOL data type, the following code executes properly on a PPC Macintosh but might not on an Intel-based Macintosh computer:

BOOL isEqual = objc_msgSend(string, @selector("isEqual:"), otherString);

To ensure that the code does executes properly on an Intel-based Macintosh computer, you would change the code to the following:

BOOL isEqual = ((BOOL (*)(id, SEL, id))objc_msgSend)(object, @selector("isEqual:"), otherString);

Open Firmware

Macintosh computers that use an Intel microprocessor do not use Open Firmware. Although many parts of the I/O registry are present and work as expected, information that is provided by Open Firmware on a PowerPC Macintosh (such as a complete device tree) is not available in the I/O registry on a Macintosh that uses an Intel microprocessor. You can obtain some of the information from IODeviceTree by using the sysctlbyname or sysctl commands.


When defining an OpenGL image or texture, you need to provide a type that specifies to OpenGL which format the texture is in. Most of these functions (for example, glTexImage2D) take format and type_ parameters that specify how the texture is laid out on disk or in memory. OpenGL supports a number of different image types; some are endian-neutral but others are not.

For example, a common image format is GL_RGBA with a type of GL_UNSIGNED_BYTE. This means that the image has a byte that specifies the red color data followed by a byte that specifies the green color data, and so forth. This format is not endian-specific; the bytes are in the same order on all architectures. Another common image format is GL_BGRA, often specified by the type GL_UNSIGNED_INT_8_8_8_8_REV. This type means that every 4 bytes of image data are interpreted as an unsigned int, with the most significant 8 bits representing the alpha data, the next most significant 8 bits representing the red color data, and so forth. Because this format is specific to the integer format of the host, the format is interpreted differently on little-endian systems than on big-endian systems. When using GL_UNSIGNED_INT_8_8_8_8_REV, the OpenGL implementation expects to find data in byte order ARGB on big-endian systems, but BGRA on little-endian systems.

Because there is no explicit way in OpenGL to specify a byte order of ARGB with 32-bit or 16-bit packed pixels (which are common image formats on Macintosh PowerPC computers), many applications specify GL_BGRA with GL_UNSIGNED_INT_8_8_8_8_REV. This practice works on a big-endian system such as PowerPC, but the format is interpreted differently on a little-endian system and causes images to be rendered with incorrect colors.

Applications that have this problem are those that use the OpenGL host-order format types, but assume that the data referred to is always big-endian. These types include, but are not limited to the following:


If your application does not use any of these types, it is unlikely to have any problems with OpenGL. Note that an application is not necessarily incorrect to use one of these types. Many applications might already present host-order data tagged with one of these formats, especially with existing cross-platform code, because the Mac OS X implementation behaves the same way as a Windows implementation.

If an application incorrectly uses one of these types, its OpenGL textures and images are rendered with incorrect colors. For example, red might appear green, or the image might appear to be tinted purple.

You can fix this problem in one of the following ways:

  1. If the images are generated or loaded algorithmically, change the code to generate the textures in host-order format that matches what OpenGL expects. For example, a JPEG decoder can be modified to store its output in 32-bit integers instead of four 8-bit bytes. The resulting data is identical on big-endian systems, but on a little-endian system, the bytes are in a different order. This matches the OpenGL expectation, and the existing OpenGL code continues to work on both architectures. This is the preferred approach.

    In many cases, rewriting the algorithms may prove a significant amount of work to implement and debug. If that’s the case, an approach that asks OpenGL to interpret the texture data differently might be a better approach for you to take.

  2. If the application uses GL_UNSIGNED_INT_8_8_8_8_REV or GL_UNSIGNED_INT_8_8_8_8, it can switch between them based on the architecture. Since these two types are exactly byte swapped versions of the same format, using GL_UNSIGNED_INT_8_8_8_8_REV on a big-endian system is equivalent to using GL_UNSIGNED_INT_8_8_8_8 on a little-endian system and vice versa. Code might look as follows:

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGRA_EXT,
    #if __BIG_ENDIAN__

    If this is a common idiom, it might be easiest to define it as a macro that can be used multiple times:

    #if __BIG_ENDIAN__
    /* later on, use it like this */
    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB,
                    width, height, 0, GL_BGRA_EXT,
                    ARGB_IMAGE_TYPE, data);

    Note that switching between GL_UNSIGNED_INT_8_8_8_8_REV and GL_UNSIGNED_INT_8_8_8_8 works only for this particular 32-bit packed-pixel data type. For 16-bit ARGB data stored using GL_UNSIGNED_SHORT_1_5_5_5_REV, there is no corresponding byte swapped type. Keep in mind that GL_UNSIGNED_SHORT_5_5_5_1 is not a replacement for GL_UNSIGNED_SHORT_1_5_5_5_REV on an Intel-based Macintosh computer. The format is interpreted as bit-order arrrrrbbbbbggggg on a big-endian system, and as bit order ggrrrrrabbbbbggg on a little-endian system.

  3. If you can’t use the previous approaches, you should either generate/load your data in the native endian format of the system and use the same pixel type on both architectures or use the GL_UNPACK_SWAP_BYTES pixel store setting to instruct OpenGL to swap the bytes of any texture loaded on a little-endian system. This setting applies to all texture or image calls made with the current OpenGL context, so it needs to be set only once per OpenGL context, for example:

    #if __LITTLE_ENDIAN__
                glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);

    This method causes images that use the problematic formats to be loaded as they would be on PowerPC. You should consider this option only if no other option is available. Enabling this option causes OpenGL to use a slower rendering path than normal. Performance-sensitive OpenGL applications may be significantly slower with this option enabled than with it off. Although this method can get an OpenGL-based program up and running in as little time as possible, it is highly recommended that you use one of the other two methods.

OSAtomic Functions

The kernel extension functions OSDequeueAtomic and OSEnqueueAtomic are not available on an Intel-based Macintosh.

For more information on these functions, see Kernel Framework Reference.

Pixel Data

Applications that store pixel data in memory using ARGB format must take care in how they read data. If the code is not written correctly, it’s possible to misread the data; the result is colors or alpha that appear wrong.

If you see colors that appear wrong when your application runs on an Intel-based Macintosh computer, the following strategy may help you identify where pixel data is being read incorrectly.

Create a test image whose pixel data is easy to identify. For example, set each pixel so that alpha is ff, red is aa, green is bb, and blue is cc. Then read that image into your application. Figure 4-1 shows such an image.

Figure 4-1  A test image that can help locate the source of color problems
A test image that can help locate the source of color problems

It's also helpful to go through your code and cast pixel data to the unsigned char data type.

Start with the portion of your code that reads the image. Use the following GDB command to examine the pixel data as hexadecimal bytes:

x/<number_bytes>xb <address of first byte>

This command prints the specified number of bytes, starting with the first byte of the first pixel. You should easily be able to see whether what’s displayed onscreen matches the values of the pixels in the test image. If the values you see do not match the test image, then you've identified the misreading problem. If the values match, then you need to identify other portions of your code that modify or transform pixel data, and inspect the pixel data after each transformation.

PostScript Printing

If you are using the Carbon Printing Manager, note that the PICT with PostScript ('pictwps') printing path is not available on Intel-based Macintosh computers except under Rosetta. If you need only to support EPS data you can use Quartz drawing together with the function PMCGImageCreateWithEPSDataProvider to allow the inclusion of EPS data as part of your Quartz drawing. If you need to generate the PostScript code for your application drawing you should use the function PMPrinterPrintWithFile.

Quartz Bitmap Data

The Quartz constants shown in Table 4-1 specify the byte ordering of pixel formats. These constants, which are defined in the CGImage.h header file, are used in the bitmapInfo parameter. To specify byte ordering to Quartz, use a bitwise OR operator to combine the appropriate constant with the bitmapInfo parameter.

Table 4-1  Quartz constants that specify byte ordering




The byte order mask


16-bit, big-endian format


32-bit, big-endian format


16-bit, little-endian format


32-bit, little-endian format


16-bit, host-endian format


32-bit, host-endian format

QuickDraw Routines

If you have existing code that directly accesses the picFrame field of the QuickDraw Picture data structure, you should use the QuickDraw function QDGetPictureBounds to get the appropriately swapped bounds for a Picture. This function is available in Mac OS X version 10.3 and later. Its prototype is as follows:

Rect * QDGetPictureBounds(
            PicHandle   picH,
            Rect        *outRect)

If you have existing code that uses the QuickDraw DeltaPoint function or the HIToolbox PinRect function (defined in MacWindows.h), make sure that you do not cast the function result to a Point data structure. The horizontal difference is returned in the low 16 bits, and the vertical difference is returned in the high 16 bits. You can obtain the horizontal and vertical values by using code similar to the following:

    Point pointDiff;
    SInt32 difference = DeltaPoint (p1, p2);
    pointDiff.h = LoWord (difference);
    pointDiff.v = HiWord (difference);

QuickTime Components

The Component Manager recognizes which architectures are supported by a component by looking at the 'thng' resource for the component, not the architecture of the file. You must specify the appropriate architectures in the 'thng' resource. To accomplish this, in the .r file where you define the 'thng' resource, modify your ComponentPlatformInfo array to look similar to the following:

#if defined(__ppc__)
kMyComponentFlags, kMyCodeType, kMyCodeID, platformPowerPCNativeEntryPoint,
#if defined(__i386__)
kMyComponentFlags, kMyCodeType, kMyCodeID, platformIA32NativeEntryPoint,

Then, rebuild your component. For details, see “Building a Universal Binary.”

QuickTime Metadata Functions

When you call the function QTMetaDataGetItemProperty and the type of the key whose value you are retrieving is code, the data returned is an OSType, not a buffer of four characters. (You can determine the key type by calling the function QTMetaDataGetItemPropertyInfo.) To ensure that your code runs properly on both PowerPC and Intel-based Macintosh computers, you must use a correctly-typed buffer so that the endian format of the data returned to you is correct. If you supply a buffer of the wrong type, for example a buffer of UInt8 instead of a buffer of OSType, the endian format of the data returned in the buffer will be wrong on Intel-based Macintosh Computers.

Runtime Code Generation

If your application generates code at runtime, keep in mind that the compiler assumes that the stack must be 16-byte aligned when calling into Mac OS X libraries or frameworks. 16-byte stack alignment is enforced on Intel-based Macintosh computers, which means that you need to ensure that your code is 16-byte aligned to avoid having your application crash.

For more information, see Mac OS X ABI Function Call Guide.

Spotlight Importers

A Spotlight importer is a plug-in bundle that extracts information from files created by an application. The Spotlight engine uses importers to gather information about new and existing files. Spotlight importers are not compatible with Rosetta. To run an importer on an Intel-based Macintosh as well as on a PowerPC-based Macintosh, you must compile it as a universal binary.

For more information on Spotlight, see Spotlight Overview andSpotlight Importer Programming Guide.

System-Specific Predefined Macros

The C preprocessor has several predefined macros whose purpose is to indicate the type of system and machine in use. If your code uses system-specific predefined macros, evaluate whether you really need to use them. In most cases applications need to know the capabilities available on a computer and not the specific system or machine on which the application is running. For example, if your application needs to know whether it is running on a little-endian or big-endian microprocessor, you should use the __BIG_ENDIAN__ or __LITTLE_ENDIAN__ macros or the Core Foundation function CFByteOrderGetCurrent. Do not use the __i386__ and __ppc__ macros for this purpose.

See GNU C 4.0 Preprocessor User Guide for additional information.

USB Device Access

USB uses little-endian format. If you are developing a universal binary version of an application that accesses a USB device, see “USB Device Access in an Intel-Based Macintosh” in USB Device Interface Guide for a discussion of the issues you may encounter.

See Also

In addition to the following resources, check the ADC website periodically for updates and technical notes that might address other specific situations: