c语言结构体在 ios蓝牙socket协议的妙用

ios中不一定需要c构建协议。但是总体来说用c语言来说相对对数据处理友好方便一些,不像oc那样笨重,毕竟c是做底层的。但是用了c处理有时候需要考虑内存释放问题。话不多说。。。

如果某些协议中只出现8位的数据,这种是相对最好处理的。例如:

如下协议:

可以构建:

typedef struct{

    uint8_t head;

    uint8_t data_1;

    uint8_t data_2;

    uint8_t place[2];

    uint8_t check;

    uint8_t tail;

}Test_struct;

对于这种类型的数据要转成oc的NSdata对象可用

Test_struct struct_data_context;

NSData *data = [NSData dataWithBytes:&struct_data_context length:sizeof(Test_struct)];

那么NSdata转该类型的结构体可用

Test_struct test_struct_data ;

[data getBytes:&test_struct_data length:sizeof(Test_struct)];

是不是很简单?不用一个一个赋值了!


但是。。。如果数据中存在16位数据 (数据分高低8位)这种情况下需要注意一下几点

1.数据大小端

2.结构体对齐(

原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。

原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)

原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

)详细的后面会提到

例如:以下协议格式(小端)

我们可以这样构建结构体,

typedef struct{    uint8_t head;    uint8_t data_1;   uint16_t data;    uint8_t place[2];    uint8_t check;    uint8_t tail;}Test_struct;

注意删除线。对于16位数据小端处理的数据,(上表第3第4字节)ios 处理器arm架构 默认处理数据都是小端传输的, uint16_t 数据映射到数组里就是低8位在前,高8位在后 形如{低8位,高8位 } 的数组,到这里大家是不是觉得很简单。NO NO NO,too 🐑 了。。。。

莫急,我们可以测试打印的 sizeof (Test_struct)= 8;

下面比较下面的协议:

我们如果按照上面逻辑我们会这样构建

typedef struct{    uint8_t head;  uint16_t data;    uint8_t place[2];    uint8_t check;    uint8_t tail;}Test_struct;

但是如果你打印一下 size 的话,你会发现sizeof(Test_struct)还是等于 8;明明比上面少一位怎么还是8位?

原因是 根据结构体原则。第二位成员2个字节,第二位成员内存从结构体开始 2字节的倍数位开始排。所以 第一个成员占了第1字节 还有个补位第二个字节,uint16个低8位占了第三个字节, uint16个高8位占了第四个字节。加上后面的4个字节,一共8个字节,第三原则(最大成员字节的整数陪)总字节数8的确是 最大成员2字节的整数倍。

那这样的话我们怎样构建结构体方便些呢?

1 。第一种把所有结构体 改成一个字节 ,意思是把uint16 高低字节拆开。(常规做法)。

2。结构体补位

第一种就不用说了,我们试下第二种怎么做。

typedef struct{ uint8_t head; uint8_t space; uint16_t data; uint8_t place[2]; uint8_t check; uint8_t tail; }Test_struct;

注意删除线。我们在head 后面补了一位。补了一位数据自然有出入,莫急。我们最后生成的时候把这一位删除数据就对了。当然方法有很多(数组遍历赋值等等),我就用内存拷贝补位前和补位后的内存这种方法。

NSData * struct2NSdata(Test_struct *context) {

        int temp_size = sizeof(Test_struct) - 1; //有效的数据字节数

        uint8_t  *temp_context = (uint8_t *)context; //强转结构体指针类型,为了后面一个字节的偏移量

        uint8_t *temp = malloc(temp_size);//分配内存

        memset(temp, 0, temp_size); //内存块初始化0

        memcpy(temp, temp_context, 1);//拷贝第一位;

        memcpy(temp + 1,temp_context + 2, temp_size - 1); //拷贝context第3位至结尾

        NSData *result = [NSData dataWithBytes:temp length:temp_size]; //最终生成的data

        free(temp); //释放开辟的内存

        return result;

}

对于NSData 转结构体也是一个办法补一位 哈哈

void nsdata2Struct(NSData *data , Test_struct *context) {

        int temp_size = data.length; //有效的数据字节数

        uint8_t *temp_context = context; //强转结构体

        uint8_t *head_data = malloc(1);

        [data getBytes:head_data range:NSMakeRange(0, 1)]; //储存前内存块

        uint8_t *tail_data = malloc(temp_size - 1);

        [data getBytes:head_data range:NSMakeRange(1, temp_size - 1)]; //储存后面内存块

        memcpy(temp_context, head_data, 1); //拷贝前内存

        memcpy(temp_context + 2, tail_data, data.length - 1); //拷贝后面的内存块 到第三字节至结尾 (忽略第二位)

        free(head_data); //释放

        free(tail_data);

}

还有结构体 第三原则 必须是最大成员的整数倍,如果不是会在结构体最后一位补位。 处理方法也和上面类似。

  综上,如果数据都是一个字节数据,构建可以什么都不用考虑,

 如果数据为小端传输,可以用上面方法,考虑一下结构体对齐,不对齐需要补位,优点是,数据转换的时候不需要一个个赋值,反正我是写的手疼。 

如果数据为大端传输,还是老老实实把成员都变成一个字节的成员变量,或者写个函数高低位转换。在用上面所提的方法。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • GNU C的一大特色就是__attribute__机制。__attribute__可以设置函数属性(Functio...
    闭家锁阅读 17,098评论 0 5
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,635评论 0 9
  • 1 Block机制 (Very Good) Block技巧与底层解析 http://www.jianshu.com...
    Kevin_Junbaozi阅读 4,000评论 3 48
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 先感叹一句:时间过的真快,2018年转眼过去2个月了。 刚好结束财报入门学习系列的文章,以及这段时间发生了一些事情...
    迹归云_周照阅读 190评论 0 0