简体   繁体   中英

Objective-c: Why is strtol method used in this code I inherited?

I recently inherited some Objective-C code and am really confused as to what it's actually doing?

1) I don't understand why the char byte_chars[3] is being populated by a '0' first and then a 0 at the end?

2) I don't understand why they used unsigned char for the wholeByte, but the put a long into it?

3) Part of me is a little confused as to what the strtol method does here, it takes 3 byte_chars bytes (which are hexadecimal), and then converts them to a long?

- (NSString *)starFromFlags:(NSString *)flags {
    unsigned char wholeByte; 
    char byte_chars[3];
    NSString *star = @"NO";

    byte_chars[0] = '0'; 
    byte_chars[1] = [flags characterAtIndex:1]; 
    byte_chars[2] = 0; 
    wholeByte = strtol(byte_chars, NULL, 16); 

    if (wholeByte & 0x01) star = @"YES";

    return star;
}

To 1:

The 0 at the end is a '\\0' (both value of zero) at the end, which means "string ends here". You have to put it at the end to end the string.

The '0' (letter 0) at the begin signals a octal value (not hexadecimal, that would be "0x") for strtol() . But as correctly mentioned by CRD (see comments), it is overriden here by the third arg passed to strtol() . So up to here you have a two-letter string with 0 the first character and the hexadecimal representation of the flags as the second character.

The reason for this is probably, that flags contains a digit from '0' to 'f'₁₆/'F'₁₆ (0 to 15₁₀).

To 2:

Since the values that can outcome from the conversion are in the range [0…15] the long value will have one of this values. You can store it in a single byte and do not need a whole long. However, strtol() always returns a long.

To 3:

Yes, it is a conversion from a string containing a number into a number. Ie the string "06" will be converted to the number 6.

Amin Negm-Awad has explained what the code does (with a minor confusion over octal), but as to answering your question:

Why is strtol method used in this code I inherited?

we can only guess.

It appears that the second character in the string is a hexadecimal digit being used for (up to) 4 flag bits, the method is testing whether the least significant of these is set. A simpler way to do this might be:

- (NSString *)starFromFlags:(NSString *)flags
{
   unichar flag = [flags characterAtIndex:1];

   if (flag > 127 || !isxdigit(flag))  // check flag is in ASCII range and hex digit
      return @"INVALID";
   else
      return digittoint(flag) & 0x1 ? @"YES" : @"NO"; // check if flag is odd hex
}

isxdigit() and digittoint() are C library functions (just like strtol() ), use man isxdigit in the Terminal for the documentation (unless you are using an older version of Xcode which has the documentation for these, Apple unhelpfully removed the docs in the latest versions). The first checks if a character is a hexadecimal digit, the second returns the integer equivalent. The > 127 check is minimal protection against non-"ASCII" characters in your string.

Note: An NSString (presents itself as) as sequence of UTF-16 code units so characterAtIndex: returns a unichar (a 16-bit type) hence the type of flag . However this code doesn't handle any unicode string correctly. If your strings are "ASCII" it will work.

The above function actually does more error checking than the original, if you are happy to reduce the error checking you can just use:

- (NSString *)starFromFlags:(NSString *)flags
{
   return digittoint([flags characterAtIndex:1]) & 0x1 ? @"YES" : @"NO";
}

This will return @"YES" if and only if the flag is a hex digit and its LSB is set, if it isn't a hex digit or the LSB isn't set it returns @"NO" . This works because digittoint() returns 0 if its argument isn't a hex digit.

So why did the original programmer use strtol() ? Maybe they didn't know about digittoint() .

HTH

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM