OC原始碼中的一些巨集

2021-08-26 11:59:11 字數 3577 閱讀 4398

#if

define(__cplusplus)

#define foundation_extern extern "c"

#else

#define foundation_extern extern

#endif

表示extern全域性變數,此時並沒有分配記憶體,需要在.m檔案中實現,為了支援c和c++混編(__cplusplus 是c++編譯器內部定義的巨集,在c++中,需要加extern 「c」或包含在extern 「c」塊中),注意,此時外界是可以修改這個值.

用法如下

foundation_extern nsstring *name// h檔案

const nsstring *name = @"gitkong"; // m檔案

extern的用法如下:

c++中extern用法

作用一:當它與」c」一起連用時,如extern 「c」 void fun(int a, int b);,則編譯器在編譯fun這個函式名時按c的規則去翻譯相應的函式名而不是c++的。

作用二:當它不與」c」在一起修飾變數或函式時,如在標頭檔案中,extern int g_nnum;,它的作用就是宣告函式或變數的作用範圍的關鍵字,其宣告的函式和變數可以在本編譯單元或其他編譯單元中使用。

即b編譯單元要引用a編譯單元中定義的全域性變數或函式時,b編譯單元只要包含a編譯單元的標頭檔案即可,在編譯階段,b編譯單元雖然找不到該函式或變數,但它不會報錯,它會在鏈結時從a編譯單元生成的目標**中找到此函式

全域性變數(extern)

有兩個類都需要使用共同的變數,我們將這些變數定義為全域性變數。比如,res.h和res.cpp分別來宣告和定義全域性變數,類producerthread和consumerthread來使用全域性變數

/**********res.h宣告全域性變數************/ 

#pragma once

#include const

int g_ndatasize = 1000; // 生產者生產的總資料量

const

int g_nbuffersize = 500; // 環形緩衝區的大小

extern char g_szbuffer; // 環形緩衝區

extern qsemaphore g_qsemfreebytes; // 控制環形緩衝區的空閒區(指生產者還沒填充資料的區域,或者消費者已經讀取過的區域)

extern qsemaphore g_qsemusedbytes; // 控制環形緩衝區中的使用區(指生產者已填充資料,但消費者沒有讀取的區域)

/**************************/

上述**中g_ndatasize、g_nbuffersize為全域性常量,其他為全域性變數。

/**********res.cpp定義全域性變數************/ 

#pragma once

#include "res.h"

// 定義全域性變數

char g_szbuffer[g_nbuffersize];

qsemaphore g_qsemfreebytes(g_nbuffersize);

qsemaphore g_qsemusedbytes;

/**************************/

在其他編譯單元中使用全域性變數時只要包含其所在標頭檔案即可。

/**********類consumerthread使用全域性變數************/ 

#include "consumerthread.h"

#include "res.h"

#include consumerthread::consumerthread(qobject* parent)

: qthread(parent)

consumerthread::consumerthread()

consumerthread::~consumerthread()

void consumerthread::run()

qdebug()<<"&&consumer over";

} /**************************/

靜態全域性變數(static)

注意使用static修飾變數,就不能使用extern來修飾,即static和extern不可同時出現。

static修飾的全域性變數的宣告與定義同時進行,即當你在標頭檔案中使用static宣告了全域性變數,同時它也被定義了。

static修飾的全域性變數的作用域只能是本身的編譯單元。在其他編譯單元使用它時,只是簡單的把其值複製給了其他編譯單元,其他編譯單元會另外開個記憶體儲存它,在其他編譯單元對它的修改並不影響本身在定義時的值。即在其他編譯單元a使用它時,它所在的實體地址,和其他編譯單元b使用它時,它所在的實體地址不一樣,a和b對它所做的修改都不能傳遞給對方。

多個地方引用靜態全域性變數所在的標頭檔案,不會出現重定義錯誤,因為在每個編譯單元都對它開闢了額外的空間進行儲存。

注:一般定義static 全域性變數時,都把它放在.cpp檔案中而不是.h檔案中,這樣就不會給其他編譯單元造成不必要的資訊汙染。

#if !defined(ns_inline)

#if defined(__gnuc__)

#define ns_inline static __inline__ __attribute__((always_inline))

#elif defined(__mwerks__) || defined(__cplusplus)

#define ns_inline static inline

#elif defined(_msc_ver)

#define ns_inline static __inline

#elif target_os_win32

#define ns_inline static __inline__

#endif

#endif

內聯函式 inline static修飾,針對當前檔案,相容 win32,適配多個編譯器環境(gnuc是gcc編譯器定義的乙個巨集;mwerks是metrowerks c/c++編譯器標識巨集;_msc_ver 是microsoft visual c++編譯器標識巨集,其中:inline、 inline 、inline 、__attribute((always_inline)) 只是不同編譯器對應的keyword而已;gnu c的一大特色就是attribute機制。attribute可以設定 函式屬性、變數屬性 和 型別屬性;例如:函式宣告中的attribute((noreturn)) ,就是告訴編譯器這個函式不會返回給呼叫者,以便編譯器在優化時去掉不必要的函式返回**)

oc中的一些常用方法

bool respondstoselector selector 用來判斷是否實現了某個方法 被封裝在乙個selector的物件裡傳遞 bool instancesrespondtoselector selector 用來判斷例項是否有以某個名字命名的方法.和上面乙個不同之處在於,前面這個方法可以用...

閱讀Peercast原始碼的一些經驗

peercast源 是我第一次看超過2萬行的 在這期間收穫很大,也積累了一些經驗。peercast源 是我第一次看超過2萬行的 在這期間收穫很大,也積累了一些經驗,在此與大家分享,希望為大家看源 提供一些幫助和參考 這裡主要介紹的是在visual stdio6.0環境下,看peercast的win3...

原始碼檢視 給你的一些建議

大家身為程式設計師的都知道,很多知識都是入門簡單,但是如果想精通的話並麼有那麼簡單的,比假如說spring幾乎上面試一次問一下,那不就是因為太重要了,隨著自己工作年限的增加,如果想擺脫乙個死工資,只能通過增加自己的底層知識點,或者接一些專案來滿足自己的需求。a 最主要的先了解底層的核心尤其重要 c ...