Objective-C知识点杂集三

第六部分

  • #define、#undef
  • 条件编译 #ifdef、#endif、#else、#ifndef

#define、#undef

  1. 预处理程序语句使用井号(#)标记,这个符号(#)必须是一行中的第一个非空格字符,但是#号后面可以允许多个空格。

  2. #define通常放在程序的开始,但在#import或include之后。但这不是必须的,它可以放在程序的任何地方。但在使用它之前,它必须已经定义了。

  3. 如果使用#define定义了一个宏,可以使用#undef取消定义


#define IPAD 1

//取消定义
#undef IPAD


条件编译 #ifdef、#endif、#else、#ifndef

#ifdef、#endif、#else、#ifndef

#ifndef:如果没有定义...

  1. 使用条件编译定义一些参数,可以让程序在不同系统上编译运行。因为不同系统可能有时候参数会不同。

例子,通过判断是否定义了IPAD来定义不同的kImageFile:


#ifdef IPAD
#  define kImageFile @"barnHD.png"
#else
#  define kImageFile @"barn.png"
#endif

#define IPAD 1
或者
#define IPAD 就足够满足定义了IPAD了

  1. 还有其他一些作用,比如调试程序。

这里没看懂???

#ifdef DEBUG
    NSLog(@"ssss");
#endif
#if、#else、#elif(相当于else if)
  • 这几个就相当于if else 语句,只不过是预处理语句形式的条件编译。语法使用和if-else语句相同

#if MAC_OC < 10.5
#define MAC xxx
#endif

  • 特殊运算符:defined (name)

#if defined(IPAD) 等于 #ifdef IPAD

#if !defined(IPAD) 等于 #ifndef IPAD


第七部分

  • 数组
  • 块(Blocks)
  • 结构体
  • 结构体指针
  • 箭头运算符(->)

数组

1. 数组的声明

数组的声明涉及数组所包含元素的数值类型,如int、float或者对象,以及将存储在数组中的最大元素数目。也就是说,对象类型也可以作为数组的元素类型

int array[100];

float array1[2][3];

NSString *strArray[100];//NSString *作为数组的元素类型

NSString *str[100] = {@"sdf",@"sdfs"};
2. 数组的初始化
  • 正如在声明数组的时候可以给它赋初值一样,也可以在声明数组的时候给数组元素赋初值。

int array[4] = {0,1,2,3};

char charArray[5] = {'a','b','c','d','e'};

  • 不必完全初始化整个数组,可以指定少数值,然后数组剩余的会自动被设为0。

float array[100] = {100.1,20.4,2003.1};

  • 可以不显式地指定数组的大小,但是必须初始化数组的每个元素

int array[] = {0,1,2,3,4,5,6};

但是不能下面这样初始化,这样初始化是错误的。不指定数组个数时,必须同时初始化。


int array[];

array = {0,1,2,3,4,5,6};
3. 二维数组的初始化
  • 第一种,使用花括号和逗号隔开每行的元素。注意花括号和逗号的使用。
int array2[3][4] = {
    
    {1,2,3,4},
    {1,2,3,4},
    {1,2,3,4}
};
  • 第二种,不使用花括号。
int array2[3][4] = {1,2,3,4,1,2,3,4,1,2,3,4};
  • 第三种,与一维数组相同,不必完全初始化所有元素。

注意:代码中两种初始化的数组元素是不同的(使用花括号,初始化的是每一行)

int array2[3][4] = {
    
    {1,2},
    {1,2,3},
    {1,2}
};

int array2[3][4] = {1,2,3,4,1};


块(Blocks)

块是Apple公司对C语言的一种扩展。

  • 可以给块传递参数,正如给函数传递一样;
  • 块也具有返回值,正如函数的返回值一样;
  • 与函数不同的是,块定义在函数或方法的内部,并且能够访问在++函数或者方法范围内++块之外的所有变量。就是说,块可以访问外部变量,但是不能超过块所在的函数或方法的范围。一般来讲,这些变量可以在块内部被访问,但是不能再块内部被修改。除非使用块修改器。

//无返回值,无参数
void (^printMessage)(void) = ^(void){
    NSLog(@"xxxxx");
};

//有返回值,两个参数
int (^calculate) (int,int) = ^(int x, int y){
    
    return x+y;
};


结构体

结构体是另一种组合元素的工具。

结构体的定义、声明和初始化
  1. 结构体的定义
//正常定义
struct date{
    int month;
    int day;
    int year;
};

//结合typedef的定义
typedef struct date{
    int month;
    int day;
    int year;
}Date;
  1. 结构体的变量声明
//正常声明
struct date today;
struct date tomorrow;

//typedef了别名的声明
Date yesterday;

//在定义结构体的时候,直接声明变量
struct date{
    int month;
    int day;
    int year;
}everyday;

注意:上面的today、tomorrow、everyday是一个结构体变量,而不是一个对象。

3.结构体变量的初始化

  • 初始化方法和数组相同。将结构体的元素放到一对花括号内。
struct date today = {1,2,3};

Date tomorrow = {1,2,3};
  • 在定义结构体的时候,直接声明并初始化变量
struct date{
    int month;
    int day;
    int year;
}everyday = {1,2,3};
  • 使用点语法初始化结构体变量。是的,结构体变量可以使用点语法,这点跟操作对象的属性一样(它的本质是存取方法)。编译器在遇到点运算符的时候,会判断左边是一个对象还是一个结构体。结构体的点语法也有存值和取值的操作。
today.month = 1;
today.day = 2;
today.year = 3;
  • 可以使用点语法,任意顺序初始化结构体变量。
struct date today = {.month=1,.today=1,.year=1};

//只将year设为1
Date tomorrow = {.year=1};
结构体中的结构体

CGPoint、CGSize、CGRect都是结构体。

  1. CGPoint用于描述(x,y)点。

在Apple的CGGeometry.h的头文件中的定义:

struct CGPoint {
    CGFloat x;
    CGFloat y;
};
typedef struct CGPoint CGPoint;

注意:CGFloat是由typedef定义的基本浮点数据类型

  1. CGSize用于描述宽和高。

在Apple的CGGeometry.h的头文件中的定义:

struct CGSize {
    CGFloat width;
    CGFloat height;
};
typedef struct CGSize CGSize;
  1. CGRect用于描述包含一个原点(一个CGPoint)和尺寸(一个CGSize)的矩形。

在Apple的CGGeometry.h的头文件中的定义:

struct CGRect {
    CGPoint origin;
    CGSize size;
};
typedef struct CGRect CGRect;

4.它们的初始化

CGRect rect = CGRectMake(0, 0, 5, 34);

CGSize size;
size.width = 1;
size.height = 1;

CGPoint point = CGPointMake(10, 11);
结构体数组
struct date{
    int month;
    int day;
    int year;
}everyday[100];

struct date today[11];

结构体指针

指向结构体变量的指针

在使用结构体定义链表或者是树的时候,我们需要指针来操作链表或树的节点,所以在声明一个链表或树的时候,我们用指针来声明。

  • 链表的结构体定义
typedef struct ListNode{
    int value;
    struct ListNode *next;
}ListNode;

  • 链表的结构体声明。(定义的结构体指针只是说明这个指针是指向这个结构的,但并未给结构体分配内存空间,这就类似于声明,只是告诉系统我这个指针是干什么用的。所以需要使用malloc)
ListNode *head;
head = (ListNode *)malloc(sizeof(ListNode));//分配内存

head->value = 1;
head->next = nil;

注意,这里使用的是箭头操作符(左边的操作数是指针时,才能使用箭头操作符。->指向的是,指针所指向的对象的成员。)

其实上面的声明和这个是相同的:

ListNode head = {1,nil};

ListNode *pHead = &head;(head取地址)

(*pHead).value = 1;

注意:点运算符比取内容运算符高*,所以这里要加上括号。

(pHead).value 就相当于 head->value*


箭头运算符(->)

C语言:存取结构体成员的点运算符(.)和箭头运算符(->)的区别

  1. 点操作符和箭头操作符的异同点
  • 相同点:两个都是二元操作符,其右操作符是成员的名称

  • 不同点:点操作符左边的操作数是一个“结果为结构”的表达式;箭头操作符左边的操作数是一个指向结构的指针

也就是说,箭头操作符的左边必须是一个指针。箭头操作符指向的是,指针所指向的对象的成员。

因为点操作符不能使用于指针,所以在链表的结构体中,使用箭头操作符。具体看结构体指针的使用。


第八部分

  • C语言中的字符串
  • 指针

C语言中的字符串

在C语言中,字符串实际上是使用 null 字符 '\0' 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。

下面的声明和初始化创建了一个 "Hello" 字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词 "Hello" 的字符数多一个。

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

其实,您不需要把 null 字符放在字符串常量的末尾。C 编译器会在初始化数组时,自动把 '\0' 放在字符串的末尾

依据数组初始化规则,您可以把上面的语句写成以下语句:

char greeting[] = "Hello";

但以下声明是错误的

char greeting[];
greeting = "Hello";

但是以下声明是错误的:

char greeting[];
greeting = "Hello";

指针

指针实际上就是内存地址

  • 可以将指针作为参数传递给方法或函数,也可以让函数或方法返回指针;
  • alloc和init返回的就是指针

例子:使用方法交换两个数字,这里传的就是指针

//交换两个数字
void exchange(int *a, int *b){
    
    int temp;
    
    temp = *a;
    *a = *b;
    *b = temp;
    
}

int main (int argc,char* argv[]){
    
    @autoreleasepool{
        
        int a = 1;
        int b = 2;
        
        exchange(&a,&b);
        
    }
    
    
}


指针与数组

oc编译器将没有下标的数组名看作是指向数组第一个元素的指针

  1. 在下面的例子里:首先定义了一个int类型的指针,然后将数组的第一个元素的指针和第二个元素的指针赋给它。*value就等于value[0],*(value+i)就等于value[i]。
int value[100];

int *valuePtr;//int类型的指针

valuePtr = value;

*valuePtr = 1;

valuePtr = value+1;

*valuePtr = 2;

NSLog(@"%d,%d",value[0],value[1]);//输出1,2
  1. 利用指针求一个数组的和
int arraySum(int array[],int n){
    
    int sum = 0 ,*ptr;
    int *arrayEnd = array + n;//注意,这里是数组的最后一个元素“之后”的指针
    
    for ( ptr = array ; ptr < arrayEnd ; ptr++ ) {
        sum += *ptr;
    }
    
    return sum;
    
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {

        int number[10] = {1,2,3,4,5,6,7,8,9,10};
        
        int result = arraySum(number,10);
        
        NSLog(@"%d",result);
    }
    return 0;
}

在这里,我们发现,给函数传递数组作为参数的时候,传递的是数组名称(实际上,传递的就是数组的首元素指针)

字符串指针
  • 利用char数组复制字符串。字符数组可以用字符串赋值,char from[] = "hello,world";换句话说,字符数组就是C风格的字符串。
void copyString(char to[],char from[]){
    
    int i;
    
    for ( i = 0 ; from[i] != '\0' ; i++ ) {
        to[i] = from[i];
    }
    
    to[i] = '\0';
    
    NSLog(@"%s",to);
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
 
        char from[] = "hello,world";
        char to[50];
        
        copyString(to, from);
    }
    return 0;
}
  • 利用指针复制字符串。注意,这里传的是指针,不是数组。
void copyString(char *to,char *from){
    
    for (  ; *from != '\0' ; to++,from++ ) {
        *to = *from;
    }
    *to = '\0';

}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
 
        char from[] = "hello,world";
        char to[50];
        
        copyString(to, from);
        NSLog(@"%s",to);
        
        copyString(to, "hello,world");
        NSLog(@"%s",to);
    }
    return 0;
}

注意:

  1. "hello,world"是C风格的字符串,不是字符串对象,字符串对象前面有@符号,这两种类型不能互相转换
  2. 字符数组 char a[] = "ssdaf dfa"; 字符数组就是C风格的字符串
  3. 如果一个函数需要传入一个char类型的数组,你可以传入一个字符数组,或者是一个字符串,而不能是字符串对象
  4. 上面的copyString(to, "hello,world"); 表明,在传递字符串的时候,实际上传递的也是指向字符串的指针。

可以这样写一个字符指针。在oc中,只要用到字符串(不是字符串对象),就会产生指向该字符串的指针。

char *textPtr = "hello,world";

第九部分

  • sizeof运算符
  • 库函数malloc
  • 一些工作原理

sizeof运算符

  • sizeof运算符用来确定数据类型或者是对象的大小

  • sizeof返回的是字节大小

  • sizeof运算符的参数可以是变量、数组名称、基本数据类型名称、对象、派生数据类型名称、表达式。

  • 获取对象的大小,要带上星号,否则返回的是指针大小:sizeof(对象)*

假设*myFract是一个Fraction的对象,它包含两个int实例变量。那么,表达式sizeof(myFract)返回的是4,在任何使用4个字节表示指针的系统上都会返回4,这是因为sizeof(myFract)表示的是指针大小。要获得实际存储Fraction对象实例的数据结构大小,要这样写:

sizeof(*myFract)

malloc

malloc用来实现动态分配内存。


一些工作原理

1. 实例变量实际上存储在结构中

定义一个新类和它的实例变量时,这些实例变量实际上存放在一个结构中。这就说明了可以如何处理对象,对象实际上是结构,结构中的成员是实例变量。所以继承的实例变量加上你再类中添加的变量就组成了一个结构。使用alloc分配对象时,系统预留了足够的空间来存储这些结构。

结构中有一个从根对象继承的成员,名为isa,它用来确定对象所属的类,它是结构的一部分,所以由对象携带。这样,运行时系统只需通过查看isa成员,就可以确定对象所属的类。

2. 对象变量实际上是指针
Fraction *myFract;

事实上是定义了一个名为myFract的指针变量。这个变量定义为指向Fraction类型的数据。

myFract = [Fraction alloc];

上面是在为Fraction对象的新势力分配内存(即存放结构的空间),然后使用结构的指针,并将指针变量myFract存储在其中。

3. id类型是通用指针类型
  • 因为通过指针(也就是内存地址)来引用对象,所以可以自由地将它们在id变量之间来回赋值。
  • 返回id类型值的方法,只是返回的某对象的指针。
  • 因为对象携带者isa成员,所以系统总是能确定id类型变量所属的类。

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

推荐阅读更多精彩内容

  • 第三部分 向对象发送消息时,如何选择正确的方法。 #import与@class指令的区别 多态 @try处理异常 ...
    拧发条鸟xds阅读 428评论 0 1
  • 第一部分 类的@interface、@implementation描述 类方法和实例方法 初步理解alloc和in...
    拧发条鸟xds阅读 390评论 0 1
  • 2017.07.26 晴 蓬莱 蓬莱,我印象中是个仙境,是有海市盛楼的地方。今天终于来身临奇境一番。感受最深的还是...
    吴兴老鱼阅读 217评论 0 1
  • 从来也没想到你发誓用一生来爱的人会对你说出那样绝情狠毒的话,至亲骨肉也敌不过一个小时的电视。觉得自己好失败,好失败...
    不要命的耿浩阅读 133评论 0 0