I consider this case as described in the link provided:
Boxing: an enumeration type value will lead to an NSNumber pointer with a creation method according to the base enumeration type, which can be a fixed base type or an integer specified by the compiler capable of representing the values ββof all members of the enumeration:
typedef enum : unsigned char { Red, Green, Blue } Color; Color col => Red; NSNumber *nsCol = @(col);
but the details of advertising campaigns in libraries are not considered, and that is where the difference in expectations is introduced.
-testA ends with a call to +[NSNumber numberWithInt:]
-testB ends with a call to +[NSNumber numberWithUnsignedInt:]
So the abstracted βpromotionβ you see is due to the fact that CFNumber (and therefore NSNumber ) does not actually support unsigned values ββat this time (see the CFNumberType enumeration constants) - based on the output you see, then it could be assumed that NSNumber implementations NSNumber simply advancing to the next signed type, capable of representing all values ββin the case of an unsigned constructor initializer - apparently without checking the value to see if any "width minimization" can be applied.
Of course, NSNumber declares constructors and initializers that accept unsigned types as parameters, but the internal representation of an unsigned integer is actually stored as a signed integer.
The compiler apparently calls the appropriate / exact convenience constructors when pushing the string literal to NSNumber . For example, a typed enum uint16_t will be saved as a 32-bit int (via numberWithUnsignedShort: , and int32_t is also a 32-bit int (via numberWithInt: . Although in the case of -testA value is also known, therefore a more suitable constructor can also be called here, therefore the compiler only minimizes the width based on the type, and not the type and value. when an enumeration type is not specified or indicated as an unsigned type, you can see such promotions.
justin
source share