一个关于整型长度的问题


我们在使用C语言编程时,却常常要考虑超出32767这个数值的数要怎么放(习惯新用int)。 而当我们使用的语言越来越抽象,越来越不需要接触到底层时。整型的长度好像再也不会成为我们考虑的问题。Objective-C语言中NSInteger是这样定义的。

typedef long NSInteger;
typedef unsigned long NSUInteger;
typedef int NSInteger;
typedef unsigned int NSUInteger;

由于Objective-C语言是基于C语言实现的,所以NSInteger既C语言的long 在32位机中最大正整数是2147483647。64位中就更不用担心位数不够用了(据说QQ曾经面临过QQ号用尽的问题)

1.问题的背景

昨天在YY狼人杀项目开发中。就出现了一个这样的BUG。
具体情况是,我们需要向服务器请求一个URL,这个URL是一个字符串并且服务器帮我们填进去了stringFormat的格式控制。
URL如下:

@"http://lanxxxxx.xx.com/x/xxxxx/index.html?gameid=%d&uid=%d&start_time=%d"

我们客户端需要将gameid,uid,start_time三个参数传入,然后使用webView打开这个URL。

NSString *str = [NSString stringWithFormat:URL,gameId,uid,startTime];
[MFWebViewController showWebViewController:str title:@""];

这里有一个隐患,既格式化字符串传入的参数是%d在Objective-C语言中是代表C语言的整型,而我们的三个参数都是uint_64。之后的问题也是由这个隐患引起的。

2.问题的出现

昨天测试拿了一台iPhone5手机过来向我提一个bug,本身应该正确显示的starTime在webView上不能正常显示,显示为2018年8月。而我iOS原生页面显示正常。第一反应是web页面解析不对。让测试去找前端开发。后面测试告诉我,所有的手机(包括iOS安卓)都能显示正常,只有这一台iPhone5显示不正常(我当时的内心(╯﹏╰))。

3.问题定位

开始排查。
web告诉我我这边传过去的starTime确实不对。而这个值是服务器提供的。依次列出可能的原因:

  1. 测试人员手机的问题。
  • 在模拟器上使用iPhone5跑了一下,发现问题复现了。那就应该不是一台手机有问题,是所有的iPhone5都不对
    这个可能性排除
  1. 在某个地方修改过数值。
  • 通过观察代码和断点测试发现,一直到push进webview页面,gameid的值都没有改变,但是输出拼接的URL时发现在URL中gameid的值与本身传入的gameid的值不符。于是定位到出错位置为:
[NSString stringWithFormat:URL,gameId,uid,startTime];

4.出错原因

由于URL是服务器传下来的,打印URL发现URL中使用%d,也既传入数据为C语言的整型。在iPhone5s及以上的机型为64位机。在C语言中int有几种长度,32位机为16位,64位机为32位。而传入的startime是一个时间戳,只有前32位有数据。所以iPhone5s及以上数据没有问题,而iPhone5是32位机,只读取了16位数据另外16位应该是寄存器中残留的数据。

5.问题解决

找到问题的原因就可以着手解决。最简单的方案是让服务器传过来用%llu作为格式控制。这样我代码也不需要修改。但是安卓反馈安卓不支持%llu格式控制。安卓的%d就包括了所有整型(这种两端不一致的问题也是很蛋疼)。最后协商,该URL不由服务器下发,写死在本地。问题得到解决。

你可能感兴趣的:(一个关于整型长度的问题)