【问题标题】:Objective-c negative Hex valuesObjective-c 负十六进制值
【发布时间】:2015-02-11 16:59:44
【问题描述】:

我在 NSData 上有以下分类方法。我正在尝试提取给定索引处的位字段并将其作为 NSNumber 返回。我让它对所有正数都有效,但我也需要它与负数一起工作。

我的实现如下所示:

#import <Foundation/Foundation.h>
@interface NSData (ExternalDevices)
@end
@implementation NSData (ExternalDevices)
- (NSNumber *)extractLittleEndianBitFieldAtIndex:(int)index forLength:(int)length
{

    //This function has limitations on the "length" parameter that are not yet know/defined
    //These limitations are due to the max size of "NSInteger intData" defined below

    int first_byte = index/8;                             //Index of the first byte containing this bit field
    int last_byte = (length+index-1)/8;                          //Index of the last byte containing this bit field
    int byte_length = last_byte - first_byte + 1;                   //number of bytes containing this bit field

    Byte *byteArray = (Byte*)malloc(byte_length);
    memcpy(byteArray, [[self subdataWithRange:NSMakeRange(first_byte, byte_length)] bytes], byte_length);

    NSInteger intData = *((NSInteger *)byteArray);

    free(byteArray);
    return [NSNumber numberWithInt:intData];
}

+ (NSData *)dataFromHexString:(NSString *)string
{
    string = [string lowercaseString];
    NSMutableData *data= [NSMutableData new];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i = 0;
    NSUInteger length = string.length;
    while (i < length-1) {
        char c = [string characterAtIndex:i++];
        if (c < '0' || (c > '9' && c < 'a') || c > 'f')
            continue;
        byte_chars[0] = c;
        byte_chars[1] = [string characterAtIndex:i++];
        whole_byte = strtol(byte_chars, NULL, 16);
        [data appendBytes:&whole_byte length:1];

    }

    return data;
}
@end



@interface Testing:NSObject
@end
@implementation Testing


- (instancetype)init
{
    self = [super init];
    if (self)
    {
        {
            NSData *data = [NSData dataFromHexString:@"e30b"];
            NSLog(@"%@ should be 3043", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]);
        }

        {
            NSData *data = [NSData dataFromHexString:@"46e0"];
            NSLog(@"%@ should be -8122", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]);
        }

        {
            NSData *data = [NSData dataFromHexString:@"f208"];
            NSLog(@"%@ should be 2290", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]);
        }

        {
            NSData *data = [NSData dataFromHexString:@"10e6"];
            NSLog(@"%@ should be -6640", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]);
        }

        {
            NSData *data = [NSData dataFromHexString:@"018900"];
            NSLog(@"%@ should be 137", [data extractLittleEndianBitFieldAtIndex:8 forLength:16]);
        }
    }
    return self;
}

@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        [[Testing alloc] init];
    }
}

以下网站似乎总能在 INT16 - Little Endian (BA) 下产生我想要的结果

http://www.scadacore.com/field-applications/miscellaneous/online-hex-converter.html

虽然重要的是要注意并非我使用的每个数字都是 INT16

【问题讨论】:

    标签: ios objective-c hex nsdata


    【解决方案1】:

    您的线路:

    NSInteger intData = *((NSInteger *)byteArray);
    

    是您的关键问题有两个原因:

    1. byteArray 可能比NSInteger 更短(或更不可能,更长),你最终会读到垃圾。例如。如果 byteArray 在您的示例中为 2 个字节,NSInteger 为 4 个字节 - 它将是 64 位 - 您将读取两个字节的垃圾。

    2. 如果要转换有符号值,则需要对值进行符号扩展 - 即将符号位复制到较高的未使用位中。例如。如果要将有符号的 16 位字段转换为 32 位有符号值,则高 16 位需要是 16 位值的最高有效位的复制,因此 0x7000 -> 0x00007000 和 0x8000 -> 0xFFFF8000 .

    您需要想出一种算法来处理这些问题。您可能会发现使用掩码(and'ing)、or'ing 和 shift 一次转换一个字节更容易。

    HTH

    【讨论】:

      猜你喜欢
      • 2014-11-30
      • 2014-03-31
      • 2012-09-08
      • 2011-02-19
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      • 2015-07-26
      • 2013-01-26
      相关资源
      最近更新 更多