typedefs and Kochan 2.0

Discussion in 'Mac Programming' started by mdeh, Jan 23, 2009.

  1. macrumors 6502

    Joined:
    Jan 3, 2009
    Messages:
    344
    #1
    On Page 219, there is a discussion about typedefs, specifically about NSComparison Result.

    I wonder if this should be updated...as per Apple's notes.


    Enumeration Constants

    A problem with enumeration (enum) constants is that their data types are frequently indeterminate. In other words, enum constants are not predictably unsigned int. With conventionally constructed enumerations, the compiler actually sets the underlying type based on what it finds. The underlying type can be (signed) int or even long. Take the following example:

    Code:
    type enum {
        MyFlagError = -1,
        MyFlagLow = 0,
        MyFlagMiddle = 1,
        MyFlagHigh = 2
    } MyFlagType;
    The compiler looks at this declaration and, finding a negative value assigned to one of the member constants, declares the underlying type of the enumeration int. If the range of values for the members does not fit into an int or unsigned int, then the base type silently becomes 64-bit (long). The base type of quantities defined as enumerations can thus change silently size to accord with the values in the enumeration. This can happen whether you're compiling 32-bit or 64-bit. Needless to say, this situation presents obstacles for binary compatibility.

    As a remedy for this problem, Apple has decided to be more explicit about the enumeration type in the Cocoa API. Instead of declaring arguments in terms of the enumeration, the header files now separately declare a type for the enumeration whose size can be specified. The members of the enumeration and their values are declared and assigned as before. For example, instead of this:

    Code:
    typedef enum {
        NSNullCellType = 0,
        NSTextCellType = 1,
        NSImageCellType = 2
    } NSCellType;
    there is now this:

    Code:
    enum {
        NSNullCellType = 0,
        NSTextCellType = 1,
        NSImageCellType = 2
    };
    typedef NSUInteger NSCellType;
    The enumeration type is defined in terms of NSInteger or NSUInteger to make the base enumeration type 64-bit capable on 64-bit architectures. For Mac OS X v10.5 all enumerations declared in the Cocoa frameworks now take this form. In some cases, an enumeration type is now declared where one had not existed before.

    Unfortunately, this change affects type checking of enumeration constants; you can pass any integer value in a method parameter typed as, say, NSCellType, not just one of the values in the enumeration. However, the change does allow more specific typing of bit masks, which were previously declared as unsigned int. You can now use the typedefs for parameters which are bit masks. For instance,

    Code:
    - (NSComparisonResult)compare:(NSString *)string options:(unsigned)mask;
    can now be

    Code:
    - (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask;
     
  2. macrumors regular

    Joined:
    Apr 1, 2006
    Messages:
    150
    Location:
    California
    #2
    Yes, you're right. The extracted typedef from the header file should be changed from this:

    Code:
    typedef enum _NSComparisonResult {
       NSOrderedAscending = -1, NSOrderedSame, NSOrderedDescending
    } NSComparisonResult;
    
    to this:
    Code:
    enum _NSComparisonResult {NSOrderedAscending = -1, NSOrderedSame, 
              NSOrderedDescending};
    
    typedef NSInteger NSComparisonResult;
    
    The troubling part of this change, as noted in Apple's notes, is that a method declared to return a value of type NSComparisonResult can now return any integer value and not just one of the enumeration values listed in _NSComparisonResult.

    Excellent catch! Thanks for pointing that out!

    Cheers,

    Steve Kochan
     

Share This Page