閒情——C語言指針和數組的探索

objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)函數是runtime中的一個函數,用來 copy 一份類對象的屬性列表,返回值爲objc_property_t *類型的數組。而後就能夠遍歷這個數組取出每一個屬性值。幾乎每一個字典轉模型框架都須要這個函數。c++

- (NSDictionary *)properties_aps {   
    NSMutableDictionary *props = [NSMutableDictionary dictionary];   
    unsigned int outCount, i;   
    objc_property_t *properties = class_copyPropertyList([self class], &outCount);   
    for (i = 0; i < outCount; i++) {   
        objc_property_t property = properties[i];   
        NSString *propertyName = [[[NSString alloc] initWithCString:property_getName(property)] autorelease];   
        id propertyValue = [self valueForKey:(NSString *)propertyName];   
        if (propertyValue) [props setObject:propertyValue forKey:propertyName];   
    }   
    free(properties);   
    return props;   
}

這段代碼中就包含了取屬性的函數:objective-c

objc_property_t *properties = class_copyPropertyList([self class], &outCount); 
for (i = 0; i < outCount; i++) {   
    objc_property_t property = properties[i];     
}

objc_property_t *類型的properties數組,取出下標,獲得的是objc_property_t類型的數組元素。數組

這個寫法忽然感受有些不解,由於若是咱們用int來代替objc_property_t框架

int main(int argc, const char * argv[]) {
    int *arr = {1,2,3};
    arr[1] = 10;
    int a = arr[1];
    NSLog(@"%d", a);
    return 0;
}

這樣顯然是不行的,int *只是一個指針,C語言中,數組的本質是指針加偏移量,因此當給arr[1]賦值時,至關因而給arr這個指針偏移了8bit,然而咱們並無爲後面的地址開闢內存空間,天然就形成了EXC_BAD_ACCESS錯誤。函數

那麼,該怎麼寫成runtime裏的那段代碼同樣type *類型的foo數組變量,能夠用foo[1]取得一個type類型的數組元素呢?學習

因此咱們要分析,上面那個int的寫法是怎麼不對的。由於在給int *arr初始化時,並無開闢一個sizeof(int)*count大小的內存空間。指針

之因此若是寫成int arr[3]就能夠,是由於這麼寫,C語言數組的本質是就是指針加偏移量。初始化了一個int指針,並且給了3*sizeof(int)大小的內存空間,返回了一個指針arr。因此,咱們能夠手動作這個步驟:code

typedef int integer;
typedef integer * integer_pointer;

integer_pointer * addIntegerToArr(integer_pointer p, ...) {
    integer_pointer *result = nil;
    if (p) {
        va_list args;
        int count = 1;
        integer_pointer current;
        va_start(args, p);
        while ((current = va_arg(args, integer_pointer))) {
            ++count;
        }
        va_end(args);
        
        result = (integer_pointer *)malloc((count) * sizeof(integer_pointer));
        result[0] = p;
        va_start(args, p);
        current = va_arg(args, integer_pointer);
        for (int i = 1; i < count; i++) {
            result[i] = current;
        }
        va_end(args);
    }
    return (integer_pointer *)result;
}

int main(int argc, const char * argv[]) {
    integer a = 10;
    integer b = 11;
    integer_pointer pa = &a;
    integer_pointer pb = &b;
    
    integer_pointer *r = addIntegerToArr(pa, pb);
    integer_pointer num = r[1];
    
    NSLog(@"%d", *num);
    return 0;
}

裏面真正關鍵的一句代碼就是result = (integer_pointer *)malloc((count) * sizeof(integer_pointer));,這樣咱們就開闢了一個內存空間,而且獲得一個integer_pointer *類型的指針,因此能夠經過對這個指針的偏移,來操做這個空間中的integer_pointer變量。對象

之因此result看起來是一個數組,能夠用result[i]這種寫法,就是由於上面的緣由。內存

因此,仍是要謹記,C語言中的數組,本質上就是指針加偏移。


雖然咱們是iOS開發者,可是畢竟C語言不能放,閒來無事能夠仿照runtime中不少C語言特徵的寫法,來實現一些語言層面的學習。雖然上面所說的內容,對真正精通C/C++的高手來講,仍是太幼稚了,可是,思考的過程仍是很是有趣。何況,在上面這個練習中,還順手學習了一下可變參數的內容。

並沒什麼過高的技術含量,因此,此篇算做閒情而已。


更多內容歡迎訪問個人博客http://suntao.me

相關文章
相關標籤/搜索