版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.10.07 |
前言
Core Foundation
框架(CoreFoundation.framework)
是一組C語言接口,它們?yōu)閕OS應(yīng)用程序提供基本數(shù)據(jù)管理和服務(wù)功能否副。接下來我們就詳細(xì)的解析這個框架。感興趣的可以看我上面寫的幾篇典阵。
1. CoreFoundation框架詳細(xì)解析(一) —— 基本概覽
2. CoreFoundation框架詳細(xì)解析(二) —— 設(shè)計概念
3. CoreFoundation框架詳細(xì)解析(三) —— 內(nèi)存管理(一)
Core Foundation Object Lifecycle Management - Core Foundation對象生命周期管理
Core Foundation對象的使用壽命取決于其引用計數(shù) - 希望對象持久存在的客戶端數(shù)量的內(nèi)部計數(shù)良狈。 在Core Foundation中創(chuàng)建或復(fù)制對象時张足,其引用計數(shù)設(shè)置為1。 隨后的客戶端可以通過調(diào)用CFRetain
來聲明對象的所有權(quán)瘟滨,CFRetain會增加引用計數(shù)候醒。 后來,當(dāng)你沒有更多的使用對象九火,你調(diào)用CFRelease
晋涣。 當(dāng)引用計數(shù)達(dá)到0時洲敢,對象的分配器釋放對象的內(nèi)存。
1. Retaining Object References - 保留對象引用
要增加Core Foundation對象的引用計數(shù)敌土,請將對該對象的引用傳遞給CFRetain
函數(shù)的參數(shù):
/* myString is a CFStringRef received from elsewhere */
myString = (CFStringRef)CFRetain(myString);
2. Releasing Object References - 釋放對象引用
要減少Core Foundation對象的引用計數(shù),請將對該對象的引用傳遞給CFRelease
函數(shù)的參數(shù):
CFRelease(myString);
重要提示:您不應(yīng)該直接釋放Core Foundation對象(例如运翼,通過對它調(diào)用free
)返干。 完成對象后,調(diào)用CFRelease
功能南蹂,Core Foundation將正確處理它犬金。
3. Copying Object References - 復(fù)制對象引用
當(dāng)您復(fù)制對象時,生成的對象的引用計數(shù)為1六剥,而不考慮原始對象的引用計數(shù)晚顷。 有關(guān)復(fù)制對象的更多信息,請參閱Copy Functions疗疟。
4. Determining an Object's Retain Count - 確定對象的保留計數(shù)
如果您想知道Core Foundation對象的當(dāng)前引用計數(shù)该默,則將對該對象的引用傳遞給CFGetRetainCount
函數(shù)的參數(shù):
CFIndex count = CFGetRetainCount(myString);
但是請注意,除了調(diào)試之外策彤,通常不需要確定Core Foundation對象的引用計數(shù)栓袖。 如果您發(fā)現(xiàn)自己需要知道對象的保留計數(shù),請檢查您是否正確遵守所有權(quán)政策規(guī)則(請參閱Ownership Policy)店诗。
Copy Functions - 復(fù)制函數(shù)
通常裹刮,當(dāng)使用=
運(yùn)算符將一個變量的值分配給另一個變量時,會發(fā)生標(biāo)準(zhǔn)復(fù)制操作(也可能稱為簡單賦值)庞瘸。例如捧弃,表達(dá)式myInt2 = myInt1
會使myInt1
的整數(shù)內(nèi)容從myInt1
使用的內(nèi)存復(fù)制到myInt2
使用的內(nèi)存中。在復(fù)制操作之后,兩個獨(dú)立的內(nèi)存區(qū)域包含相同的值违霞。但是嘴办,如果您嘗試以這種方式復(fù)制Core Foundation對象,請注意买鸽,您不會重復(fù)對象本身涧郊,僅僅是對對象的引用。
例如眼五,Core Foundation的新用戶可能會認(rèn)為要創(chuàng)建CFString
對象的副本妆艘,她將使用表達(dá)式myCFString2 = myCFString1
。同樣看幼,此表達(dá)式實(shí)際上并不復(fù)制字符串?dāng)?shù)據(jù)双仍。因為myCFString1和myCFString2都必須具有CFStringRef
類型,所以此表達(dá)式僅復(fù)制對該對象的引用桌吃。復(fù)制操作后朱沃,您有兩份CFString的引用。這種類型的副本非趁┯眨快逗物,因為只有引用是重復(fù)的,但重要的是要記住以這種方式復(fù)制可變對象是危險的瑟俭。與使用全局變量的程序一樣翎卓,如果應(yīng)用程序的一部分使用引用的副本更改對象,那么程序的其他具有該引用副本的部分就無法知道數(shù)據(jù)已更改摆寄。
如果要復(fù)制對象失暴,則必須使用Core Foundation提供的函數(shù)之一專門用于此目的。繼續(xù)使用CFString示例微饥,您將使用CFStringCreateCopy
創(chuàng)建一個包含與原始數(shù)據(jù)相同的數(shù)據(jù)的全新CFString對象逗扒。具有CreateCopy
函數(shù)的Core Foundation類型還提供了可以修改的對象的副本CreateMutableCopy
的變體。
1. Shallow Copy - 淺拷貝
復(fù)制復(fù)合對象欠橘,可以包含其他對象的集合對象等對象也必須小心處理矩肩。正如您所期望的,使用=
運(yùn)算符對這些對象執(zhí)行副本會導(dǎo)致對象引用的重復(fù)肃续。與CFString
和CFData
這樣的簡單對象相反黍檩,為復(fù)合對象(如CFArray和CFSet)提供的CreateCopy
函數(shù)實(shí)際上會執(zhí)行淺拷貝。在這些對象的情況下始锚,淺層復(fù)制意味著創(chuàng)建新的集合對象刽酱,但是原始集合的內(nèi)容不會被復(fù)制 - 只有對象引用被復(fù)制到新的容器。如果您有一個不可變的數(shù)組瞧捌,并且您想對其進(jìn)行重新排序棵里,則此類型的副本很有用。在這種情況下,您不想復(fù)制所有包含的對象衍慎,因為不需要更改它們,以及為什么要使用額外的內(nèi)存皮钠?您只需要更改包含的對象集稳捆。與使用簡單類型復(fù)制對象引用相同的風(fēng)險也適用。
2. Deep Copy - 深拷貝
當(dāng)您要創(chuàng)建一個全新的復(fù)合對象時麦轰,必須執(zhí)行深層復(fù)制乔夯。 深層復(fù)制復(fù)制復(fù)合對象及其所有對象的內(nèi)容。 Core Foundation的當(dāng)前版本包括執(zhí)行屬性列表深度復(fù)制的函數(shù)(請參閱CFPropertyListCreateDeepCopy)款侵。 如果要創(chuàng)建其他結(jié)構(gòu)的深層副本末荐,則可以通過遞歸遞減到復(fù)合對象并逐個復(fù)制其所有內(nèi)容來執(zhí)行深層副本。 當(dāng)復(fù)合對象可以遞歸時新锈,請注意實(shí)現(xiàn)此功能 - 它們可以直接或間接包含對其自身的引用 - 這可能導(dǎo)致遞歸循環(huán)甲脏。
Byte Ordering - 字節(jié)排序
微處理器架構(gòu)通常使用兩種不同的方法將多字節(jié)數(shù)字?jǐn)?shù)據(jù)的各個字節(jié)存儲在存儲器中。這種差異被稱為byte ordering
或endian nature
妹笆。大多數(shù)情況下块请,您的計算機(jī)的端序格式可以被安全地忽略,但在某些情況下拳缠,它變得至關(guān)重要墩新。 OS X提供了一種將數(shù)據(jù)的一種端形式轉(zhuǎn)化為另外一種端模式的各種函數(shù)。
Intel x86
處理器首先存儲最低有效字節(jié)的雙字節(jié)整數(shù)窟坐,后跟最高有效字節(jié)海渊。這稱為小端字節(jié)排序。其他CPU(如PowerPC CPU)首先存儲其最高有效字節(jié)的雙字節(jié)整數(shù)哲鸳,后跟其最低有效字節(jié)臣疑。這被稱為大字節(jié)字節(jié)排序。大多數(shù)時候徙菠,您的計算機(jī)的端序格式可以安全地忽略朝捆,但在某些情況下,它變得至關(guān)重要懒豹。例如芙盘,如果您嘗試從與您的端點(diǎn)性質(zhì)不同的計算機(jī)上創(chuàng)建的文件讀取數(shù)據(jù),則字節(jié)排序的差異可能會產(chǎn)生不正確的結(jié)果脸秽。從網(wǎng)絡(luò)讀取數(shù)據(jù)時也會發(fā)生同樣的問題儒老。
術(shù)語:術(shù)語big-endian
和little-endian
來自Jonathan Swift的十八世紀(jì)諷刺Gulliver的旅行。 Blefuscu帝國的主體被分為兩個派系:從大端開始吃蛋的人和從小端起吃蛋的人记餐。
給出一個討論端格式問題的具體例子驮樊,考慮一個簡單的C結(jié)構(gòu)的例子,它定義了兩個四字節(jié)整數(shù),如Listing 1所示囚衔。
// Listing 1 Example data structure
struct {
UInt32 int1;
UInt32 int2;
} aStruct;
假設(shè)Listing 2中所示的代碼用于初始化Listing 1所示的結(jié)構(gòu)挖腰。
// Listing 2 Initializing the example structure
ExampleStruct aStruct;
aStruct.int1 = 0x01020304;
aStruct.int2 = 0x05060708;
考慮Figure 1中的圖表,其中顯示了大端處理器或內(nèi)存系統(tǒng)如何組織示例數(shù)據(jù)练湿。 在大端系統(tǒng)中猴仑,物理內(nèi)存被組織,每個字節(jié)的地址從最高到最低的肥哎。
請注意辽俗,這些字段存儲在左側(cè)的更高有效字節(jié)和右側(cè)較少有效字節(jié)。 這意味著地址字段Int1
的最高有效字節(jié)的地址是0x98
篡诽,而地址0x9B
對應(yīng)于Int1
的最低有效字節(jié)崖飘。
圖2中的圖表顯示了一個小端系統(tǒng)如何組織數(shù)據(jù)。
請注意杈女,每個字段的最低地址現(xiàn)在對應(yīng)于最低有效字節(jié)朱浴,而不是最高有效字節(jié)。如果要在小端系統(tǒng)上打印Int1的值达椰,您將看到盡管以不同的字節(jié)順序存儲赊琳,但它仍然被正確解釋為十進(jìn)制值16909060。
現(xiàn)在假設(shè)由Listing 2所示的代碼初始化的示例數(shù)據(jù)值是在小端系統(tǒng)上生成并保存到磁盤砰碴。假設(shè)數(shù)據(jù)以字節(jié)地址順序?qū)懭氪疟P躏筏。當(dāng)通過大端系統(tǒng)從磁盤讀取時,數(shù)據(jù)將再次布置在存儲器中呈枉,如Figure 2所示趁尼。問題是數(shù)據(jù)仍然是小端字節(jié)順序,即使它是在大型端系統(tǒng)猖辫。該差異導(dǎo)致值被錯誤評估酥泞。在本示例中,Int1域的十進(jìn)制值應(yīng)為16909060啃憎,但是由于字節(jié)排序不正確芝囤,因此它被評估為67305985.這種現(xiàn)象稱為字節(jié)交換,一般發(fā)生在當(dāng)一個端格式的數(shù)據(jù)被使用其他字符串格式時辛萍。
不幸的是悯姊,這是一般情況下無法解決的問題。原因是您交換的方式取決于數(shù)據(jù)的格式贩毕。字符串通常不會被交換悯许,長字交換四字節(jié)到端,字交換兩個字節(jié)端到端辉阶。因此先壕,需要交換數(shù)據(jù)的任何程序必須知道數(shù)據(jù)類型瘩扼,源數(shù)據(jù)端序和主機(jī)端序。
CFByteOrder.h
中的函數(shù)允許您對雙字節(jié)和四字節(jié)整數(shù)以及浮點(diǎn)值進(jìn)行字節(jié)交換垃僚。適當(dāng)使用這些功能可以幫助您確保程序操作的數(shù)據(jù)正確集绰。有關(guān)使用這些函數(shù)的詳細(xì)信息,請參閱Byte Swapping 部分谆棺。 請注意栽燕,Core Foundation的字節(jié)交換函數(shù)僅適用于OS X。
Using Allocators in Creation Functions - 在創(chuàng)建函數(shù)中使用分配器
每個Core Foundation不透明類型都有一個或多個創(chuàng)建函數(shù)包券,該函數(shù)創(chuàng)建并返回以特定方式初始化的該類型的對象。所有創(chuàng)建函數(shù)都將其作為第一個參數(shù)作為對分配器對象(CFAllocatorRef)
的引用炫贤。某些函數(shù)也可能具有用于專門分配和釋放目的的分配器參數(shù)溅固。
分配器參考參數(shù)有幾個選項:
- 你可以傳遞常量
kCFAllocatorSystemDefault
,這指定了通用系統(tǒng)分配器(它是初始默認(rèn)分配器)兰珍。 - 您可以傳遞
NULL
來指定當(dāng)前的默認(rèn)分配器(可能是自定義分配器或通用系統(tǒng)分配器)侍郭。這與傳遞kCFAllocatorDefault
相同。 - 您可以傳遞常量
kCFAllocatorNull
掠河,該常量指示不分配的分配器亮元,嘗試使用它是錯誤的。一些創(chuàng)建函數(shù)具有用于重新分配或釋放后備存儲的特殊分配器的參數(shù)唠摹,通過為參數(shù)指定kCFAllocatorNull
爆捞,可以防止自動重新分配或釋放。 - 您可以使用
CFGetAllocator
函數(shù)獲得另一個Core Foundation對象使用的分配器的引用勾拉。通過使用相同的分配器分配它們煮甥,可以將相關(guān)對象放入內(nèi)存zone
中。 - 您可以傳遞對自定義分配器的引用(請參閱Creating Custom Allocators)藕赞。
如果要使用自定義分配器成肘,并且要使其成為默認(rèn)分配器,建議首先使用CFAllocatorGetDefault
函數(shù)獲取對當(dāng)前默認(rèn)分配器的引用斧蜕,并將其存儲在局部變量中双霍。完成使用自定義分配器后,使用CFAllocatorSetDefault
函數(shù)將存儲的分配器重置為默認(rèn)分配器批销。
Using the Allocator Context - 使用分配器上下文
Core Foundation中的每個分配器都有一個上下文洒闸。 上下文是定義對象的操作環(huán)境的結(jié)構(gòu),通常由函數(shù)指針組成均芽。 分配器的上下文由CFAllocatorContext
結(jié)構(gòu)定義顷蟀。 除了函數(shù)指針之外,結(jié)構(gòu)還包含版本號和用戶定義數(shù)據(jù)的字段骡技。
// Listing 1 The CFAllocatorContext structure
typedef struct {
CFIndex version;
void * info;
const void *(*retain)(const void *info);
void (*release)(const void *info);
CFStringRef (*copyDescription)(const void *info);
void * (*allocate)(CFIndex size, CFOptionFlags hint, void *info);
void * (*reallocate)(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info);
void (*deallocate)(void *ptr, void *info);
CFIndex (*preferredSize)(CFIndex size, CFOptionFlags hint, void *info);
} CFAllocatorContext;
info
字段包含分配器的任何特別定義的數(shù)據(jù)鸣个。 例如羞反,分配器可以使用info
字段來跟蹤特殊的分配。
重要提示:對于當(dāng)前版本囤萤,不要將version
字段的值設(shè)置為0以外的任何值昼窗。
如果在分配器上下文(info字段)中有一些用戶定義的數(shù)據(jù),請使用CFAllocatorGetContext
函數(shù)獲取分配器的CFAllocatorContext
結(jié)構(gòu)涛舍。 然后根據(jù)需要評估或處理數(shù)據(jù)澄惊。 以下代碼提供了一個示例:
// Listing 2 Getting the allocator context and user-defined data
static int numOutstandingAllocations(CFAllocatorRef alloc) {
CFAllocatorContext context;
context.version = 0;
CFAllocatorGetContext(alloc, &context);
return (*(int *)(context.info));
}
其他Core Foundation函數(shù)調(diào)用在分配器上下文中定義的與內(nèi)存相關(guān)的回調(diào),并將一個無類型的指針取回或返回到一個內(nèi)存塊(void *):
-
CFAllocatorAllocate
富雅,分配一個內(nèi)存塊掸驱。 -
CFAllocatorReallocate
,重新分配一塊內(nèi)存没佑。 -
CFAllocatorDeallocate
毕贼,取消分配一塊內(nèi)存。 -
CFAllocatorGetPreferredSizeForSize
蛤奢,根據(jù)給定的一個請求鬼癣,給出了可能被分配的內(nèi)存大小。
Creating Custom Allocators - 創(chuàng)建自定義分配器
要創(chuàng)建自定義分配器啤贩,首先聲明并初始化CFAllocatorContext
類型的結(jié)構(gòu)待秃。 將版本字段初始化為0,并將任何所需的數(shù)據(jù)(如控制信息)分配并分配給info
字段痹屹。 此結(jié)構(gòu)的其他字段是在下面的Implementing Allocator Callbacks中描述的函數(shù)指針章郁。
一旦將適當(dāng)?shù)闹捣峙浣oCFAllocatorContext
結(jié)構(gòu)的字段,則調(diào)用CFAllocatorCreate
函數(shù)來創(chuàng)建allocator對象志衍。 該函數(shù)的第二個參數(shù)是指向結(jié)構(gòu)的指針驱犹。 此函數(shù)的第一個參數(shù)標(biāo)識用于為新對象分配內(nèi)存的分配器。 如果要在CFAllocateContext
結(jié)構(gòu)中為此使用allocate
回調(diào)足画,請為第一個參數(shù)指定kCFAllocatorUseContext
常量雄驹。 如果要使用默認(rèn)分配器,請在此參數(shù)中指定NULL
淹辞。
// Listing 1 Creating a custom allocator
static CFAllocatorRef myAllocator(void) {
static CFAllocatorRef allocator = NULL;
if (!allocator) {
CFAllocatorContext context =
{0, NULL, NULL, (void *)free, NULL,
myAlloc, myRealloc, myDealloc, NULL};
context.info = malloc(sizeof(int));
allocator = CFAllocatorCreate(NULL, &context);
}
return allocator;
}
1. Implementing Allocator Callbacks - 實(shí)現(xiàn)分配器回調(diào)
CFAllocatorContext
結(jié)構(gòu)有七個定義回調(diào)函數(shù)的字段医舆。 如果創(chuàng)建自定義分配器,則必須至少實(shí)現(xiàn)allocate
函數(shù)象缀。 分配器回調(diào)應(yīng)該是線程安全的蔬将,如果回調(diào)函數(shù)調(diào)用其他函數(shù),它們也應(yīng)該是重入的央星。
保留霞怀,釋放和復(fù)制描述回調(diào)都以CFA1locatorContext
結(jié)構(gòu)的info
字段為單參數(shù)。 鍵入為void *
莉给,此字段指向您為分配器定義的任何數(shù)據(jù)毙石,例如包含控制信息的結(jié)構(gòu)體廉沮。
Retain
回調(diào):
const void *(*retain)(const void *info);
在info
中保留您為分配器上下文定義的數(shù)據(jù)。 這只有在數(shù)據(jù)是Core Foundation對象時才有意義徐矩。 您可以將此函數(shù)指針設(shè)置為NULL
滞时。
Release
回調(diào)
void (*release)(const void *info);
Release(或free)您為分配器上下文定義的數(shù)據(jù)。 您可以將此函數(shù)指針設(shè)置為NULL
滤灯,但這樣做可能會導(dǎo)致內(nèi)存泄漏坪稽。
Copy Description
回調(diào):
CFStringRef (*copyDescription)(const void *info);
返回對描述您的分配器的CFString
的引用,特別是用戶定義數(shù)據(jù)的某些特性鳞骤。 您可以將此函數(shù)指針設(shè)置為NULL窒百,在這種情況下,Core Foundation將提供基本描述豫尽。
Allocate
回調(diào)
void * (*allocate)(CFIndex size, CFOptionFlags hint, void *info);
分配至少size
字節(jié)的內(nèi)存塊篙梢,并返回指向塊開頭的指針。 hint
參數(shù)是一個你現(xiàn)在應(yīng)該不使用的位域拂募。 size
參數(shù)應(yīng)該始終大于0庭猩,如果不是窟她,或者發(fā)生分配問題陈症,返回NULL
。 此回調(diào)可能不為NULL
震糖。
Reallocate
回調(diào)
void * (*reallocate)(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info);
將由ptr
指向的內(nèi)存塊的大小更改為由newsize
指定的大小录肯,并將指針返回到較大的內(nèi)存塊。 在任何重新分配失敗時返回NULL
吊说,使舊的內(nèi)存塊不變论咏。 請注意,ptr
參數(shù)永遠(yuǎn)不會為NULL
颁井,而newsize
將始終大于0 - 除非滿足這兩個條件厅贪,否則不使用該回調(diào)。
將舊內(nèi)存塊的內(nèi)容保持不變雅宾,直到較小的新尺寸或舊尺寸养涮。 如果ptr
參數(shù)不是先前由分配器分配的內(nèi)存塊,則結(jié)果未定義眉抬;異常程序終止可能發(fā)生贯吓。 hint
參數(shù)是一個你現(xiàn)在應(yīng)該不使用的位域。 如果將此回調(diào)設(shè)置為NULL
蜀变,則當(dāng)它嘗試使用該分配器時悄谐,CFAllocatorReallocate
函數(shù)在大多數(shù)情況下返回NULL。
Deallocate
回調(diào)
void (*deallocate)(void *ptr, void *info);
使ptr
指向的內(nèi)存塊可用于分配器的后續(xù)重用库北,但不可用于程序的繼續(xù)使用爬舰。 ptr參數(shù)不能為NULL们陆,如果ptr參數(shù)不是先前由allocator
分配的內(nèi)存塊,則結(jié)果未定義洼专,異常程序終止可能發(fā)生棒掠。 您可以將此回調(diào)設(shè)置為NULL,在這種情況下屁商,CFAllocatorDeallocate
函數(shù)不起作用烟很。
Preferred Size
回調(diào)
CFIndex (*preferredSize)(CFIndex size, CFOptionFlags hint, void *info);
返回分配器可能分配的實(shí)際大小,給出對size
大小的內(nèi)存塊的請求蜡镶。 hint
參數(shù)是一個你現(xiàn)在應(yīng)該不使用的位域雾袱。
Byte Swapping - 字節(jié)交換
如果您需要找到主機(jī)字節(jié)順序,您可以使用函數(shù)CFByteOrderGetCurrent
官还。 可能的返回值為CFByteOrderUnknown
芹橡,CFByteOrderLittleEndian
和CFByteOrderBigEndian
。
1. Byte Swapping Integers - 字節(jié)交換整數(shù)
Core Foundation為字節(jié)交換提供了三個優(yōu)化的基本功能 - CFSwapInt16
望伦,CFSwapInt32
和CFSwapInt64
林说。 所有其他交換函數(shù)都使用這些原語完成他們的工作。 一般來說屯伞,您不需要直接使用這些原語腿箩。
盡管原始交換功能無條件交換,但是較高級別的交換功能是以不需要字節(jié)交換的方式進(jìn)行定義的劣摇,換句話說珠移,當(dāng)源和主機(jī)字節(jié)順序相同時,它們不會執(zhí)行任何操作末融。 對于整數(shù)類型钧惧,這些函數(shù)采用CFSwapXXXBigToHost
和CFSwapXXXLittleToHost
,CFSwapXXXHostToBig
和CFSwapXXXHostToLittle
的格式勾习,其中XXX
是諸如Int32
的數(shù)據(jù)類型浓瞪。 例如,如果您在一個小端點(diǎn)機(jī)器上讀取數(shù)據(jù)為網(wǎng)絡(luò)字節(jié)順序(big-endian)的網(wǎng)絡(luò)中的16位整數(shù)值巧婶,則可以使用函數(shù)CFSwapInt16BigToHost
乾颁。 Listing 1演示了這個過程。
// Listing 1 Swapping a 16 bit Integer
SInt16 bigEndian16;
SInt16 swapped16;
// Swap a 16 bit value read from network.
swapped16 = CFSwapInt16BigToHost(bigEndian16);
Byte Ordering部分介紹了一個簡單的C結(jié)構(gòu)示例粹舵,該C結(jié)構(gòu)創(chuàng)建并保存到小端機(jī)上的磁盤钮孵,然后從大端機(jī)器上的磁盤讀取。 為了糾正這種情況眼滤,您必須交換每個字段中的字節(jié)巴席。 Listing 2中的代碼演示了如何使用Core Foundation字節(jié)交換函數(shù)來完成此操作。
// Listing 2 Byte swapping fields in a C structure
// Byte swap the values if necessary.
aStruct.int1 = CFSwapInt32LittleToHost(aStruct.int1)
aStruct.int2 = CFSwapInt32LittleToHost(aStruct.int2)
假設(shè)一個大端的架構(gòu)诅需,Listing 2中使用的函數(shù)將交換每個字段中的字節(jié)漾唉。 Figure 1顯示了字段交換對aStruct.int1
字段的影響荧库。 請注意,字節(jié)交換代碼在小端機(jī)上運(yùn)行時不會執(zhí)行任何操作赵刑。 編譯器應(yīng)優(yōu)化代碼并保留數(shù)據(jù)不變分衫。
2. Byte Swapping Floating-Point Values - 字節(jié)交換浮點(diǎn)值
即使在單個平臺上,浮點(diǎn)值也可以有許多不同的表示形式般此。 除非你非常小心蚪战,否則嘗試在平臺邊界上傳遞浮點(diǎn)值會讓人無盡的頭疼。 為了幫助您處理浮點(diǎn)數(shù)铐懊,Core Foundation定義了一組函數(shù)和兩個特殊的數(shù)據(jù)類型以及整數(shù)交換函數(shù)邀桑。 這些函數(shù)允許您對32位和64位浮點(diǎn)值進(jìn)行編碼,以便稍后對其進(jìn)行解碼科乎,并在必要時進(jìn)行字節(jié)交換壁畸。 Listing 3 顯示了如何編碼64位浮點(diǎn)數(shù),Listing 4顯示了如何解碼它茅茂。
// Listing 3 Encoding a Floating Point Value
Float64 myFloat64;
CFSwappedFloat64 swappedFloat;
// Encode the floating-point value.
swappedFloat = CFConvertFloat64HostToSwapped(myFloat64);
// Listing 4 Decoding a floating-point value
Float64 myFloat64;
CFSwappedFloat64 swappedFloat;
// Decode the floating-point value.
myFloat64 = CFConvertFloat64SwappedToHost(swappedFloat);
數(shù)據(jù)類型CFSwappedFloat32
和CFSwappedFloat64
在規(guī)范表示中包含浮點(diǎn)值捏萍。 CFSwappedFloat
本身不是浮點(diǎn)數(shù),不應(yīng)該直接用作浮點(diǎn)數(shù)空闲。 然而令杈,您可以發(fā)送一個到另一個進(jìn)程,保存到磁盤或通過網(wǎng)絡(luò)發(fā)送进副。 由于格式是通過轉(zhuǎn)換函數(shù)轉(zhuǎn)換為規(guī)范格式的这揣,因此不需要顯式交換API悔常。 如果需要影斑,在格式轉(zhuǎn)換過程中,會為您處理字節(jié)交換机打。
后記
未完矫户,待續(xù)~~~