来自 NSData 的 Objective-c sscanf

eag*_*poo 1 scanf objective-c bit-shift

我有一个 BTLE 设备,它向我发送字节,其中一些我需要组成一个 32 位有符号整数,移位,然后解释。我正在使用 xcode 6.1。

我遇到的问题是简单地使用 sscanf 将字节转换为 int32_t ,这有时有效,有时无效。我不是 obj-c 专家,不确定这是否是正确的方法,我使用的 strtol 同样不起作用。

整个功能如下:

- (double) parseMV2: (NSData*) data {
  NSData* slicedData = [data subdataWithRange:NSMakeRange(2, 4)];
  const char *bytes = [slicedData bytes];
  int32_t value;
  double mV = 0;

  int sscanf_result = sscanf(bytes, "%4x", &value);

  if (1 == sscanf_result) {
    value <<= 3; // discard the 3 most significant bits as they are not part of the value this also brings the sign bit to the most significant bit position.
    value >>= 8; // discard the 5 least significant bits as they are below the noise levels.
    mV = ((double)value)*2048.0/16777216.0; // Convert to mV
  } else {
    NSLog(@" sscanf failed to read bytes %4x (result = %d)", (int32_t) bytes, sscanf_result);
  }

  NSLog(@"     mV2 = %f (bytes = %x", mV, (uint) bytes);
  NSLog(@"----------------------------------");

  return mV;
}
Run Code Online (Sandbox Code Playgroud)

如果我在 sscanf 之后设置断点,有时 value 会被设置为字节的正确解释,但通常它只是设置为零。这是 llvm 的一些输出:

(lldb) print bytes
(const char *) $3 = 0x17ecceb8 "+\333\x91"
(lldb) print value
(int32_t) $4 = 0
Run Code Online (Sandbox Code Playgroud)

这是另一个示例,其中 sscanf 再次返回 0 但值不是 0(不要这样做,因为我认为 sscanf 返回它实际分配给的变量数):

(lldb) print bytes
(const char *) $6 = 0x176db558 ")Z\x19x"
(lldb) print value
(int32_t) $7 = 383772
Run Code Online (Sandbox Code Playgroud)

rma*_*ddy 5

使用sscanf用于从 C 字符串读取,但您没有 C 字符串。你有一个字节序列。

试试这个方法:

NSData* slicedData = [data subdataWithRange:NSMakeRange(2, 4)];
const uint8_t *bytes = [slicedData bytes];
int32_t value;
memcpy(&value, bytes, 4);
Run Code Online (Sandbox Code Playgroud)

正如 Ken 所指出的,更简单的方法是:

int32_t value;
[data getBytes:&value range:NSMakeRange(2, 4)];
Run Code Online (Sandbox Code Playgroud)

根据数据的创建方式,您可能还需要担心字节顺序。您可能需要添加:

value = CFSwapInt32BigToHost(value); // or CFSwapInt32LittleToHost
Run Code Online (Sandbox Code Playgroud)

  • 这大致是正确的方法,但为什么不使用 `-[NSData getBytes:range:]` 而不是制作切片然后使用 `memcpy()`?`[data getBytes:&amp;value range:NSMakeRange(2, 4)];` (3认同)