c和OC
1.程序运行时,计算机会将相应的文件复制到内存(RAW)中去,执行文件中的命令。
2.不同CPU,汇编语言不同
3."高级语言",不考虑特定CPU,使用统一的方法发布指令,然后由编译器来将这些代码转换成经过高度优化的,针对特定CPU的机器编码。
4.OC是以C为基础的,增加了对面向对象编程的支持。
Xcode
1.有些程序没有图形化的用户界面,但可以长时间运行,称之为守护进程(daemon)。比如复制粘贴时就用到了pdoard。
2.还有只能在相爱terminal上运行的程序,称之为命令行工具。
3.C语言编写完成程序后,编译器会将程序转换成机器吗,当点击run按钮时,Xcode会运行这个编译器(编译器也是一个程序)。此处的(编译一个程序)和(构建一个程序)值的是一件事。
4.运行程序时,计算机会将变异后的程序从硬盘拷贝至内存,然后处理器会执行程序的main函数,main函数会再调用其他函数。
函数
5.1计算机在运行程序时,会将这些函数从硬盘拷贝至内存,然后找到名为“main”的函数并执行。
5.4 标准库
其中一些文件包含一组预先编译过的函数。这些组文件被称为标准库(standard libraries)。
标准库由多个文件构成,其中两个文件为stdio.h及unistd.h
如果在你的程序中包含这两个文件,就可以使用文件中包含的函数,例如stdio.h文件中的printf()函数,以及unistd.h中的sleep()函数
标准库有两大作用:
1.包含大量程序员无需自己编写和维护的代码。与自己编写的代码相比,使用标准库可以构建出更复杂,更好的程序。
2.确保大多数程序有相当的共通性。
5.5帧(frame)和栈(stack)
帧可以用来保存函数执行时的数据,当函数执行结束后,帧被销毁。
A函数中,调用的B函数,当运行时,B函数被调用了,A函数在等待B函数,这时,A函数存在于栈中
栈用来描述帧在内存中的存贮的地点,执行函数时,函数的帧会在栈的顶部被创建出来。函数执行结束时,我们会说函数返回了,也就是说,其帧会退出栈。等待下一个调用他的函数继续执行。
格式化字符串
printf("It was the best of times.\n");
char *str = "It was the best of times.\";
printf(*str);
//这两者是一样的
1.格式说明符
char *str = "It ";
printf("这个是%s。\n",str );
//str中的内容会替换%s
%s == 数据类型是一个字符串
%d == 数据类型是一个整数
2.转义字符
\n 转义字符 换行
整数
1.整数
UInt32 x; //无符号32位整数
SInt16 y; //有符号16位整数
char a;//8位
short b;//一般是16位
int c;//一般是32位
long d;//32位或64位,视平台而定
long long e;//64位
int x =255
printf("x is %d.\n", x); //十进制输出
printf("x is %o.\n", x);//八进制
printf("x is %x.\n", x);//十六进制
x is 255
x is 377
x is ff
NSInteger NSUInteger有符号,无符号
int i =3;
while (i<12){
char s = "qqqq"
printf("%s\n",s );
i++;
}
for(int i=0;i<10;i++){
printf("qqqq\n");
}
do{
char s = "qqqq"
printf("%s\n",s );
i++;
}while(i<12);
break跳出整个循环
continue 跳出余下,执行下一次循环。
9地址和指针
9.1获取地址
变量的地址,是指内存中的某个位置,该位置的内存保存着变量的值,通过&运算符,可以得到变量的地址。
int i =17;
printf("i stores its value at %p\n",&i );
i stores its value at 0xbffff738
任何一个函数都有自己的地址,通过函数的函数名,就能得到相应函数的地址
printf("this function starts at %p\n",main );
9.2用指针保存地址
只要是大小合适的无符号整数,就可以保存指针。
当数据很大很复杂时,指针的好处就体现出来了。这是因为程序不一定能通过拷贝来传递数据,但是一定能够直接传递或通过拷贝来传递数据的起始地址。
9.3通过地址访问数据
使用*运算符,可以访问保存在某个地址中的数据。
int i =17
int *add = &i;
9.4不同类型数据所占字节大小
sizeof()可以得到某个数据类型的大小
sizeof(int)
sizeof(*int)
9.5 NULL
使用空指针,不指向任何地址。有一个能够保存地址的指针变量,但是要赋上某个值,用于明确表示该指针没有指向任何地址。
9.6代码规范
float power 而不是 float power
float a,b,c;都是float
float *a,b;a是指针,b是float
float a,b;都是指针
通过引用传递
C语言标准库中有一个modf()函数,调用该函数并传入一个都变了的数,可以得到浮点数的整数部分和小数部分。例如3.14。可以得到整数部分3和小数部分0.14
调用modf()函数时,需要传入一个地址供modf()函数保存整数部分的计算结果,准确的说,modf()会返回小数部分,然后将整数部分拷贝至传入的地址。
double pi =3.14;
double integerPart;
double fractionPart;
fractionPart = modf(pi,&integerPart);
printf("integerPart = %.0f,fractionPart = %.2f/n",integerPart,fractionPart);
编写通过引用传递参数的函数
void metersToFeetAndInches(double meters,unsigned int *ftPtr,double *inPtr){
double rawFeet = meters * 3.281;
unsigned int feet = (unsigned int)floor(rawFeet);
*ftPtr = feet;
double fractionFoot = rawFeet - feet;
double inches = fractionFoot *12.0;
*inPtr = inches;
}
double meters = 3.0;
unsigned int feet ;
double inches;
metersToFeetAndInches(meters,&feet,&inches);
不要对NULL取值
结构
编写程序时,需要一个变量保存多个数据
struct Person
{
float heightInMeters;
int weightInKilos;
};
int main(int argc, char const *argv[])
{
struct Person mikey;
mikey.heightInMeters = 1.7;
return 0;
}
在声明类型为结构的变量时,每次都要用Stuct这样很麻烦。
可以用typedef
typedef struct{
float heightInMeters;
int weightInKilos;
} Person;
int main(int argc, char const *argv[])
{
Person miki;
return 0;
}
堆
前几章使用的都是栈中的内存,这类内存空间会在调用函数时由系统自动分配,并在函数结束之后自动释放。这也是局部变量常被称为自动变量的原因。
仅有自动变量是不够的,有时还要“申请”一块连续的内存-缓冲区(buffer)。编程术语中的缓冲区常被用来表示一块连续的内存,缓冲区来自特定的内存区域--堆(heap)
在堆上,缓冲区独立于任何函数的栈,因此,他可以在多个函数中使用。例如,你可以声明一个缓冲区存储一些文本文件,然后调用某个函数将文本文件保存至缓冲区中。再点用另一个函数来统计文本中字母的个数,最后在调用一个函数来进行校对。处理完文本文件之后,就可以将缓冲区的这块内存还给堆。
使用malloc()函数可以得到一块内存缓冲区。当程序不再使用这块缓冲区时,可以调用free()函数,释放相应的内存,将其返还给堆
int main(int argc, char const *argv[])
{
float *startOfBuffer;
startOfBuffer = malloc(1000*sizeof(float));
free(startOfBuffer);
*startOfBuffer = NULL;
return 0;
}
typedef struct{
float a;
int b;
}Person;
float bodyMassIndex(Person *p){
return p->a/(p->a+p->b);
}
int main(int argc, char const *argv[])
{
Person *mike = (Person *)malloc(sizeof(Person));
mike->a = 12.2;
mike->b = 333;
free(mike);
mike = NULL;
return 0;
}
对象
import和#include区别
import指令导入更快更有效率,会让编译器先检查之前是否已经导入过这个文件
include指令告诉编译器做呆板的复制粘贴
import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSDate *now = [NSDate date];
}
return 0;
}
详解消息
给新对象发送消息,比如发送timeIntervalSince1970
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSDate *now = [NSDate date];
NSLog(@"This NSDate object lives at %p",now);
NSLog(@"This date is %@",now);
double secondes = [now timeIntervalSince1970];
NSLog(@"it has been %f seconds since the start 1970",secondes);
}
return 0;
}
发送错误消息
区分大小写
命名习惯
方法名第一个单词小写开头,后面的单词大写开头
类的名称大写字母开头,接下来的单词也大写开头
再谈消息
14.1传递实参消息
接受方 实参
| |
\_/ \_/
[now dateByAddingTimeInterval:100000]
/-\
|
选择器
14.2多个实参
接受方 实参
| |
\_/ \_/
[cal ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:now]
/-\
|
选择器
14.3消息的嵌套发送
NSDate *now = [NSDate date];
double seconds = [now timeIntervalSince1970];
//也可以嵌套起来
double seconds = [[NSDate date] timeIntervalSince1970];
14.4 alloc和init
唯一必须使用嵌套的形式连续发送的消息是alloc和init
每个类都有一个alloc类方法。它能够创建一个新的对象,并返回指向该对象的指针。通过alloc创建出来的对象,必须经过初始化才能使用。如果创建出来的新对象没有经过初始化,它会存在于内存里,但是无法接受消息。每个类也都有一个init实例方法,它用来初始化实例。
NSDate *now = [[NSDate alloc]init];
14.5向nil发送消息
几乎所有的面相对象的语言都会有nil这样的概念:不指向任何对象的指针。在Objective-C中,nil的值为0的指针。
多数面向对象的语言不允许向nil发送消息。所以在发送消息前,必须检查指针是否为nil,从而导致出现大量下面这类代码:
if(fido!=nil){
[fido foGetTheNewspaper];
}
OC则不同,在OC中,可以向nil发送消息。什么事情也不会发生。因此下面这段代码是合法的:
Dog *filo =nil;
[filo goGetTheNewsPaper];
<font color=#0099ff size=12 face="黑体">重点1:</font>如果程序向某个对象发送了消息,但却没有得到预期的结果,请检查消息接受方是否为nil。
<font color=#0099ff size=12 face="黑体">重点2:</font>向nil发送消息,得到的返回值没有意义
14.6 id
当声明指向对象的指针式,通常都会明确地写出相应对象的类:
NSDate *expiration;
但是在编写程序是,很可能会碰到以下这种情况:声明指针时并不知道所指对象的准确类型。为此,可以使用id类型。id类型的含义是:可以指向任意类型Objective-C对象的指针
再谈消息
14.1传递实参消息
接受方 实参
| |
\_/ \_/
[now dateByAddingTimeInterval:100000]
/-\
|
选择器
14.2多个实参
接受方 实参
| |
\_/ \_/
[cal ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:now]
/-\
|
选择器
14.3消息的嵌套发送
NSDate *now = [NSDate date];
double seconds = [now timeIntervalSince1970];
//也可以嵌套起来
double seconds = [[NSDate date] timeIntervalSince1970];
14.4 alloc和init
唯一必须使用嵌套的形式连续发送的消息是alloc和init
每个类都有一个alloc类方法。它能够创建一个新的对象,并返回指向该对象的指针。通过alloc创建出来的对象,必须经过初始化才能使用。如果创建出来的新对象没有经过初始化,它会存在于内存里,但是无法接受消息。每个类也都有一个init实例方法,它用来初始化实例。
NSDate *now = [[NSDate alloc]init];
14.5向nil发送消息
几乎所有的面相对象的语言都会有nil这样的概念:不指向任何对象的指针。在Objective-C中,nil的值为0的指针。
多数面向对象的语言不允许向nil发送消息。所以在发送消息前,必须检查指针是否为nil,从而导致出现大量下面这类代码:
if(fido!=nil){
[fido foGetTheNewspaper];
}
OC则不同,在OC中,可以向nil发送消息。什么事情也不会发生。因此下面这段代码是合法的:
Dog *filo =nil;
[filo goGetTheNewsPaper];
<font color=#0099ff size=12 face="黑体">重点1:</font>如果程序向某个对象发送了消息,但却没有得到预期的结果,请检查消息接受方是否为nil。
<font color=#0099ff size=12 face="黑体">重点2:</font>向nil发送消息,得到的返回值没有意义
14.6 id
当声明指向对象的指针式,通常都会明确地写出相应对象的类:
NSDate *expiration;
但是在编写程序是,很可能会碰到以下这种情况:声明指针时并不知道所指对象的准确类型。为此,可以使用id类型。id类型的含义是:可以指向任意类型Objective-C对象的指针
网友评论