结构体的转换

值对象(value object)概念

在面向对象的编程语言中,值对象本质上是数据元素的的对象包装器,所谓数据元素,常见的包含string,number,date类型以及其它自定义的结构体类型。Objective-C语言本身提供了string,number,date相对应的包装类,分别是NSString,NSNumber,NSDate,这些类创建的对象都可以称为值对象。但值对象本身的范围更加广泛,它可以是任何自定义类型创建的对象。

值对象作用

C语言提供了char/int/float/double基本数据类型,基于C语言的Objective-C因此同样包含了这几种基本数据类型,我们可以定义并使用这些基本数据类型的变量,也可以使用其对应的值对象,对于自定义数据类型,我们也可以将由这些类型定义的变量通过NSValue来包装成对象类型。相对于普通的变量,值对象提供了更多的功能和作用。

1.可将任何值对象存储在集合中。

在Objective-C中,诸如NSArray,NSDictionary这样的集合类所包含的元素必须是对象类型。因此基本数据类型的变量必须转换为值对象才能存储在集合中。

2.更加更加丰富的数据处理方法。

NSString或NSMulableString可以进行一系列针对字符串的操作,如字符串的连接,分割,查找,比较,提取字符等等。

NSDate和NSCaleder可进行复杂的日期处理和计算,所有这些计算都考虑了时区和闰年的影响。

NSNumber和NSDecimalNumber可以处理 char, short int, int, long int, long long int, float, or double , BOOL值,并提供了数值与字符串的转换

NSValue释义

上面我们已经提到NSValue可包装基本数据类型为对象类型,下面我们来看下Apple官方文档释义:

NSValue提供了简单的容器来包含C或Objective-C数据项。可以容纳任何基本数据类型如char,int,float,double,以及指针,结构体和对象ids。NSArray和NSSet集合类对象要求它们的元素为对象类型,NSValue的主要目的是使这些数据类型可以添加至集合中。NSValue对象是不可变类型。

简而言之,NSValue是基本数据类型或自定义数据类型所定义变量的对象包装器。

使用NSValue

1.处理NSRange,方法

?


1

2

+ (NSValue *)valueWithRange:(NSRange)range

- (NSRange)rangeValue

如,

?


1

2

3

4

5

6

7

8

9

10

11

12

13

NSRange rangeA ;

rangeA.location = 0 ;

rangeA.location = 10 ;

// 创建NSRange的值对象

NSValue *rangeValue = [NSValue valueWithRange:rangeA] ;

// 重新获取值对象包含的值 

NSRange rangeB = [rangeValue rangeValue] ;

NSLog(@"%d,%d",rangeB.location , rangeB.length) ; // 10,10

2.处理自定义结构体类型,方法

?


1

2

3

+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type

- (id)initWithBytes:(const void *)value objCType:(const char *)type

- (void)getValue:(void *)buffer

如:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// 结构体定义

typedef struct{

   int a ;

   float b ;    

}DataItem ;

DataItem dataElemA  ;

    

dataElemA.a = 10 ;

    

dataElemA.b = 10.005 ;

    

NSValue *value = [NSValue valueWithBytes:&dataItem objCType:@encode(DataItem)] ;

    

DataItem dataElemB ;

    

[value getValue:&dataElemB] ;

    

NSLog(@"%d,%0.3f",dataElemB.a,dataElemB.b); // 10,10.005

自定义类型必须是固定长度类型,不能将C字符串,可变长度的数组和结构体,以及其它变长类型存储在NSValue中,这些可变类型应该使用NSString或NSData来包装成对象类型。但可以将可变数据类型的指针保存在NSValue中,官方文档示例: 
    
        原意想要保存myCString到NSValue中,但实际上myCString是以char的指针类型进行解析的,所以字符串的前四个字节被当做了指针的值,而不是地址值来对待。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

/* INCORRECT! */

char *myCString = "This is a string.";

NSValue *theValue = [NSValue valueWithBytes:myCString objCType:@encode(char *)];

char *cc = (char*)malloc(sizeof(char*)*200) ;

   

[theValue getValue:cc];

  

prinf("%s" , cc)  ; // This

   

free(cc)

正确的做法是保存字符串到NSString中,如,

?


1

2

3

char *myCString = "This is a string.";

   

NSString myNsString = [NSString stringWithCString:myCString encoding:NSUTF8StringEncoding] ;

或者,保存该字符串的指针地址到NSValue中,如,

?


1

2

3

4

5

6

7

8

9

10

11

12

13

char *myCString = "This is a string.";

   

NSValue *theValue = [NSValue valueWithBytes:&myCString objCType:@encode(char **)];

    

 char **cc = (char**)malloc(sizeof(char**)*200) ;

   

[theValue getValue:cc];

    

printf("----%s----" , *cc); // This is a string.

   

free(cc) ;

cc = NULL ;

3.处理指针类型,方法

?


1

2

+ (NSValue *)valueWithPointer:(const void *)aPointer

- (void *)pointerValue

如:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

DataItem *dd = (DataItem*)malloc(sizeof(DataItem)) ;

dd->a = 1 ;

dd->b = 2 ;

    

NSValue *pValue = [NSValue valueWithPointer:dd] ;

    

DataItem *dc = (DataItem*)[pValue pointerValue] ;

    

NSLog(@"%d,%0.3f",dc->a,dc->b);

    

free(dd) ;

    

dd = NULL ;

    

dc = NULL ;

NSValue的分类

UIKit Additions

提供了Function框架中关于几何数据类型结构体的对象值包装,包括CGPoint,CGRect,CGSize,CGAffineTransform,UIEdgeInsets,UIOffset。

以CGPoint为例(其它的结构体都有相对应的方法),方法

?


1

2

+ (NSValue *)valueWithCGPoint:(CGPoint)point

- (CGPoint)CGPointValue

如:

?


1

2

3

4

5

6

7

8

9

CGPoint origin = CGPointMake(10.0 , 10.0) ;

        

NSValue *ptValue = [NSValue valueWithCGPoint:origin] ;

        

NSArray *ptArr = [NSArray arrayWithObject:ptValue];

        

NSValue *ptValueB = [ptArr objectAtIndex:0] ;

        

CGPoint originB = [ptValueB CGPointValue] ;

时间: 2024-12-25 22:25:34

结构体的转换的相关文章

字节序转换与结构体位域(bit field)值的读取 Part 2 - 深入理解字节序和结构体位域存储方式

上一篇文章讲解了带位域的结构体,在从大端机(Big Endian)传输到小端机(Little Endian)后如何解析位域值.下面继续深入详解字节序,以及位域存储的方式. (1) 我们知道,存储数字时,对小端机而言,数字的低位,存在低地址,高位存在高地址.大端机正相反. (2) 读取的方式,也是一样的.对于小端机,读出的低地址位作为数字的低位. (3) 此外Big-Endian/Little-Endian存储顺序,不仅仅针对字节,还针对字节内的比特位.对于小端机而言,字节内的8个比特,低地址端比

C#结构体和字节数组的转换函数

在通信过程中,一般我们都会操作到字节数组.特别是希望在不同语言编程进行操作的时候. 虽然C#提供了序列化的支持,不用字节数组也行.但操作字节数组肯定会碰到. 一般都会采用结构来表示字节数组.但结构与字节数组直接的转换实在很麻烦. 字节操作不但容易出错,而且每增加一个结构,就自己实现一遍,实在是烦不胜烦. 有没有简单的方法呢?当然有.可以采用非托管区的一些方法来实现. 首先,导入命名空间:System.Runtime.InteropServices; 定义结构的时候,要给结构指定特性. 如: //

将传入结构体 pMtInfo 中包含的数据内容转换成 JSON 字符串返回

upu_struct.h封装了有关  pMtInfo结构体的内容,用到的部分如下图所示: 利用jansson库实现将传入结构体 pMtInfo 中包含的数据内容转换成 JSON 字符串返回 代码如下: #include <stdio.h> #include <string.h> #include "jansson.h" #include "upu_struct.h" #include "upu_proto_parse.h"

串口数据传输当中的共用体和结构体转换

嵌入式系统的串口数据传输都是以字节为单位,但是有些特殊的数据类型,比如float a=231.5,在最底层是如何表示的呢?我们知道float数据类型占用4个字节,实际上在内存当中a=0x43678000,只是嵌入式芯片访问a时,知道a是浮点型数据,所以一次性读取4个字节,而且也按照浮点型的数据表示规定,将a转换为十进制的可读数据231.5.如果我们从串口接收到4个字节数据{0x43,0x67,0x80,0x00},如何把这4个字节的数据转换为float型呢?直接令float a=0x436780

C结构体与Json字符串自动转换

我们知道在Java中利用Gson这个包可以很方便地将Object和Json进行自动转换(串行化/反串行化).其原理是利用了Java的反射机制. 最近我的项目中需要将C结构体与Json自动互转.项目背景其实是一个类似protobuf的json协议生成与解析,协议很多,所以我们肯定是希望从一个C结构体的对象自动转成Json,不然协议一条一条自己写,手筋要累断. 要实现这个需求,首先就要给C结构体加入反射机制.我的处理方法是让用户在定义结构体时,额外再定义一个metainfo,用于保存这个结构体的反射

用隐式转换实现类型或结构体直接赋值

在vs中敲一句string s="aaa"; 你会发现string是个class,一般咱们给类型赋值的时候都是先new一个,然后再给其属性赋值,string却能直接赋值,顿时感觉很神奇 当然,在stirng s = "aaa";中,右面的“aaa”它其实就是个string类型,所以直接=是没有问题的 但是,由string s ="aaa";我们就可以提出一个假象,咱们自己定义的class能不能也实现类似的效果呢? 答案显然是肯定的~~~~ 这需要

C#与C++数据类型比较及结构体转换(搜集整理二)

原文网址:http://www.blogjava.net/heting/archive/2010/03/20/315998.html C++ C# ===================================== WORD ushort DWORD uint UCHAR int/byte 大部分情况都可以使用int代替,而如果需要严格对齐的话则应该用bytebyte UCHAR* string/IntPtr unsigned char* [MarshalAs(UnmanagedType

C#中结构体与字节流互相转换

1.定义与C++对应的C#结构体 在c#中的结构体不能定义指针,不能定义字符数组,只能在里面定义字符数组的引用. C++的消息结构体如下: //消息格式 4+16+4+4= 28个字节 struct cs_message{ u32_t cmd_type; char username[16]; u32_t dstID; u32_t srcID; }; C#定义的结构体如下: [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct

结构体与字符串之间的转换

UIKIT_EXTERN NSString *NSStringFromCGPoint(CGPoint point);UIKIT_EXTERN NSString *NSStringFromCGSize(CGSize size);UIKIT_EXTERN NSString *NSStringFromCGRect(CGRect rect);UIKIT_EXTERN NSString *NSStringFromCGAffineTransform(CGAffineTransform transform);