一、(一共三十题)
1.main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
答案:2,5
*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5。a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)
int *ptr=(int *)(&a+1);
则ptr实际是&(a[5]),也就是a+5
原因如下:a是数组指针,其类型为int (*)[5];而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同。a是长度为5的int数组指针,所以要加5*sizeof(int),以ptr实际是a[5]。但是prt与(&a+1)类型是不一样的(这点很重要)。所以prt-1只会减去sizeof(int*),a,&a的地址是一样的,但意思不一样。a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].
2.以下为Windows NT下的32位C++程序,请计算sizeof的值
void Func ( char str[100])
{sizeof( str ) = ?}
void *p = malloc( 100 );
sizeof ( p ) = ?
答案:sizeof( str )、sizeof ( p )都为4。
3.还是考指针,不过我对cocoa的代码还是不太熟悉大概是这样的- NSString *getNSString(void)
{
NSString *output=@"Thisis a main test\n";
return output;
}
-main(void)
{NSString *a=@"Main";
NSString *aString = [NSStringstringWithString:@"%@",getNSString(a)];NSLog(@"%@\n", aString);
}
答案:最后问输出的字符串:NULL,output在函数返回后,内存已经被释放。
4.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个。
答案:#defineSECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
5.写一个委托的interface
答案:@protocol MyDelegate;
@interface MyClass: NSObject
{
id delegate;
}
//委托方法
@protocol MyDelegate
- (void)didJobs:(NSArray*)args;
@end
6.写一个NSString类的实现-(id)initWithCString:(const char *)nullTerminatedCStringencoding:(NSStringEncoding)encoding; -(void)dealloc;
答案:+ (id) stringWithCString:(const char*)nullTerminatedCString
encoding: (NSStringEncoding)encoding
{
NSString*obj;
obj = [self allocWithZone:NSDefaultMallocZone()];
obj = [obj initWithCString:nullTerminatedCString encoding: encoding];
return AUTORELEASE(obj);
}
7.obj-c有多重继承么?不是的话有什么替代方法?
答案:cocoa中所有的类都是NSObject的子类,多继承在这里是用protocol委托代理来实现的,你不用去考虑繁琐的多继承,虚基类的概念.ood的多态特性在obj-c中通过委托来实现.
8.obj-c有私有方法么?私有变量呢
答案:objective-c -类里面的方法只有两种,静态方法和实例方法
在Objective‐C中,所有实例变量默认都是受保护的,所有实例方法默认都是公有的
9.关键字const有什么含意?关键字volatile有什么含意?并给出三个不同的例子。static关键字的作用,extern "C"的作用
答案:const意味着"只读",声明一个参数为常量是为了告诉了用户这个参数的应用目的。
关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果
你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清
理的。)
通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初
始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指
定为const;
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。
static关键字的作用:
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值;
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明
它的模块内;
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
extern "C"的作用
(1)被extern
"C"限定的函数或变量是extern类型的;
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,
其声明的函数和变量可以在本模块或其它模块中使用。
(2)被extern
"C"修饰的变量和函数是按照C语言方式编译和连接的;
extern "C"的惯用法
(1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:
extern "C"
{#include "cExample.h"}
而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。
(2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不
能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。
10.为什么标准头文件都有类似以下的结构?#ifndef __INCvxWorksh#define __INCvxWorksh#ifdef __cplusplusextern "C" {#endif/*...*/#ifdef __cplusplus}#endif#endif /*__INCvxWorksh */
答案:显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif”的作用是防止该头文件被重复引用。
11.#import跟#include的区别,@class呢?
答案:@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import而#import比起#include的好处就是不会引起交叉编译
12.MVC模式的理解
答案:MVC设计模式考虑三种对象:模型对象、视图对象、和控制器对象。模型对象代表特别的知识和专业技能,它们负责保有应用程序的数据和定义操作数据的逻辑。视图对象知道如何显示应用程序的模型数据,而且可能允许用户对其进行编辑。控制器对象是应用程序的视图对象和模型对象之间的协调者。
13.线程与进程的区别和联系?线程是否具有相同的堆栈? dll是否有独立的堆栈?
答案:进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
14.列举几种进程的同步机制,并比较其优缺点。进程之间通信的途径进程死锁的原因死锁的4个必要条件死锁的处理
答案:同步机制:原子操作,信号量机制,自旋锁,管程,会合,分布式系统
进程之间通信的途径:共享存储系统消息传递系统管道:以文件系统为基础
进程死锁的原因:资源竞争及进程推进顺序非法
死锁的4个必要条件:互斥、请求保持、不可剥夺、环路
死锁的处理:鸵鸟策略、预防策略、避免策略、检测与解除死锁
15.堆和栈的区别
答案:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
申请大小:栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。
16.什么是键-值,键路径是什么
答案:模型的性质是通过一个简单的键(通常是个字符串)来指定的。视图和控制器通过键来查找相应的属性值。在一个给定的实体中,同一个属性的所有值具有相同的数据类型。键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制。
键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。第一个键的性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。键路径使您可以以独立于模型实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性。
17.c和obj-c如何混用
答案:1)obj-c的编译器处理后缀为m的文件时,可以识别obj-c和c的代码,处理mm文件可以识别obj-c,c,c++代码,但cpp文件必须只能用c/c++代码,而且cpp文件include的头文件中,也不能出现obj- c的代码,因为cpp只是cpp。
2)在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是问题
3)在cpp中混用obj- c其实就是使用obj-c编写的模块是我们想要的。
如果模块以类实现,那么要按照cpp class的标准写类的定义,头文件中不能出现obj-c的东西,包括#import cocoa的。实现文件中,即类的实现代码中可以使用obj-c的东西,可以import,只是后缀是mm。如果模块以函数实现,那么头文件要按c的格式声明函数,实现文件中,c++函数内部可以用obj-c,但后缀还是mm或m。
总结:只要cpp文件和cpp include的文件中不包含obj-c的东西就可以用了,cpp混用obj-c的关键是使用接口,而不能直接使用实现代码,实际上cpp混用的是obj-c编译后的o文件,这个东西其实是无差别的,所以可以用。obj-c的编译器支持cpp.
18.目标-动作机制
答案:目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参见"插座变量"部分)的形式保有其动作消息的目标。
动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现的方法。程序需要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制。
19.cocoa touch框架
答案:iPhone OS应用程序的基础Cocoa Touch框架重用了许多Mac系统的成熟模式,但是它更多地专注于触摸的接口和优化。UIKit为您提供了在iPhone OS上实现图形,事件驱动程序的基本工具,其建立在和Mac OS X中一样的Foundation框架上,包括文件处理,网络,字符串操作等。
Cocoa Touch具有和iPhone用户接口一致的特殊设计。有了UIKit,您可以使用iPhone OS上的独特的图形接口控件,按钮,以及全屏视图的功能,您还可以使用加速仪和多点触摸手势来控制您的应用。
各色俱全的框架除了UIKit外,Cocoa Touch包含了创建世界一流iPhone应用程序需要的所有框架,从三维图形,到专业音效,甚至提供设备访问API以控制摄像头,或通过GPS获知当前位置。Cocoa Touch既包含只需要几行代码就可以完成全部任务的强大的Objective-C框架,也在需要时提供基础的C语言API来直接访问系统。这些框架包括:
Core Animation:通过Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。
Core Audio:Core Audio是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。
Core Data:提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。
下面是Cocoa Touch中一小部分可用的框架:
音频和视频:Core Audio、OpenAL、Media Library、AV Foundation
数据管理:Core Data、SQLite
图形和动画:Core Animation、OpenGL ES、Quartz 2D
网络/li>:onjour、WebKit、BSD Sockets
用户应用:Address Book、Core Location、ap Kit、tore Kit
20.objc的内存管理
答案:1、如果您通过分配和初始化(比如[[MyClass alloc]
init])的方式来创建对象,您就拥有这个对象,需要负责该对象的释放。这个规则在使用NSObject的便利方法new时也同样适用。
2、如果您拷贝一个对象,您也拥有拷贝得到的对象,需要负责该对象的释放。
3、如果您保持一个对象,您就部分拥有这个对象,需要在不再使用时释放该对象。反过来,如果您从其它对象那里接收到一个对象,则您不拥有该对象,也不应该释放它(这个规则有少数的例外,在参考文档中有显式的说明)。
21.自动释放池是什么,如何工作
答案:当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。
1.ojc-c是通过一种"referring counting"(引用计数)的方式来管理内存的,对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一,每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0,系统才会调用dealloc真正销毁这个对象.
2. NSAutoreleasePool就是用来做引用计数的管理工作的,这个东西一般不用你管的.
3. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一.
22.类工厂方法是什么(就是便利构造器)
答案:类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中,返回被创建的对象,并进行自动释放处理。这些方法的形式是+ (type)className...(其中className不包括任何前缀)。
工厂方法可能不仅仅为了方便使用。它们不但可以将分配和初始化合在一起,还可以为初始化过程提供对象的分配信息。
类工厂方法的另一个目的是使类(比如NSWorkspace)提供单件实例。虽然init...方法可以确认一个类在每次程序运行过程只存在一个实例,但它需要首先分配一个“生的”实例,然后还必须释放该实例。
工厂方法则可以避免为可能没有用的对象盲目分配内存。
23.单件实例是什么
答案:Foundation和Application Kit框架中的一些类只允许创建单件对象,即这些类在当前进程中的唯一实例。举例来说,NSFileManager和NSWorkspace类在使用时都是基于进程进行单件对象的实例化。当向这些类请求实例的时候,它们会向您传递单一实例的一个引用,如果该实例还不存在,则首先进行实例的分配和初始化。单件对象充当控制中心的角色,负责指引或协调类的各种服务。如果类在概念上只有一个实例(比如NSWorkspace),就应该产生一个单件实例,而不是多个实例;如果将来某一天可能有多个实例,您可以使用单件实例机制,而不是工厂方法或函数。
24.动态绑定
答案:动态绑定——在运行时确定要调用的方法。动态绑定将调用方法的确定也推迟到运行时。在编译时,方法的调用并不和代码绑定在一起,只有在消实发送出来之后,才确定被调用的代码。通过动态类型和动态绑定技术,您的代码每次执行都可以得到不同的结果。运行时因子负责确定消息的接收者和被调用的方法。运行时的消息分发机制为动态绑定提供支持。当您向一个动态类型确定了的对象发送消息时,运行环境系统会通过接收者的isa指针定位对象的类,并以此为起点确定被调用的方法,方法和消息是动态绑定的。而且,您不必在Objective-C代码中做任何工作,就可以自动获取动态绑定的好处。您在每次发送消息时,特别是当消息的接收者是动态类型已经确定的对象时,动态绑定就会例行而透明地发生。
25.obj-c的优缺点
答案:objc优点:1) Cateogies 2) Posing()3)动态识别4)指标计算5)弹性讯息传递6)不是一个过度复杂的C衍生语言7) Objective-C与C++可混合编程
缺点: 1)不支援命名空間2)不支持运算符重载3)不支持多重继承4)使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函等),性能低劣。
26.sprintf,strcpy,memcpy使用上有什么要注意的地方
答案:strcpy是一个字符串拷贝的函数,它的函数原型为strcpy(char *dst,
const char *src);将src开始的一段字符串拷贝到dst开始的内存中去,结束的标志符号为'\0',由于拷贝的长度不是由我们自己控制的,所以这个字符串拷贝很容易出错。
具备字符串拷贝功能的函数有memcpy,这是一个内存拷贝函数,它的函数原型为memcpy(char *dst, const
char* src, unsigned int len);将长度为len的一段内存,从src拷贝到dst中去,这个函数的长度可控。但是会有内存叠加的问题。
sprintf是格式化函数。将一段数据通过特定的格式,格式化到一个字符串缓冲区中去。sprintf格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲区的大小,造成溢出。
27.用变量a给出下面的定义
a)一个整型数(An integer)
b)一个指向整型数的指针(A pointer to an integer)
c)一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a
pointer to an intege)r
d)一个有10个整型数的数组(An array of 10 integers)
e)一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10
pointers to integers)
f)一个指向有10个整型数数组的指针(A pointer to an array of 10
integers)
g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to afunction that takes an integer as an argumentand returns an integer)
h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(An array of ten
pointers to functions t hat take an integer argument and return an integer)
答案:
a) int a; // An integer
b) int *a; // A pointer toan integer
c) int **a; // A pointer toa pointer to an integer
d) int a[10]; // An array of10 integers
e) int *a[10]; // An arrayof 10 pointers to integers
f) int (*a)[10]; // Apointer to an array of 10 integers
g) int (*a)(int); // A pointerto a function a thattakes an integerargument and returns an integer
h) int (*a[10])(int); // Anarray of 10 pointers to functionsthattake an integer argument and return an integer
28.cocoa有哪些设计模式?
答案:
29.socket编程中如何判断异步connect是否成功
答案:创建一个socket,设为异步socket(fcntl),将socket加入epoll,connect到远端(此时connect调用返回非0,但errno为EINPROGRESS,表示正在建立连接中)
epoll_wait之捕获到EPOLLOUT事件,此时便认为connect已经成功,client端开始发消息
这个过程通常能够运转,但是线上环境复杂多变,如果发生这种情况:server进程调用listen开始侦听后,被gdb或信号挂住了,此时异步connect会怎样?很遗憾,client端的epoll_wait依然返回EPOLLOUT,甚至往此socket里发消息都返回成功,只有当发的消息多得占完了server端的tcp缓冲以后(窗口收缩到很小),send调用才开始失败。这时候用losf -i看网络连接也很有趣,client端的机器显示连接建立了,server端的却显示没有这个连接。
仔细想想,OS这样做是正确的,毕竟connect的语义只是“连接”,当server挂住时,连接还是能成功的,但你能不能往里面发消息那就是另外一回事了。
所以对于应用来说,异步socket想要知道connect后连接是不是可以正常收发数据了,还是要靠应用层的一问一答才能知道。
30.[[[nil
retain]retain]release]有什么问题
答案:没有问题
31.cocoa架构
答案:
32.readwrite,readonly,assign,retain,copy,nonatomic属性的作用
答案:@property是 一个属性访问声明,扩号内支持以下几个属性:
1.getter=getterName,setter=setterName,设置setter与getter的方法名
2.readwrite,readonly,设置可供访问级别
3.assign,setter方法直接赋值,不进行 任何retain操作,为了解决原类型与环循引用问题
4.retain,setter方法对参数进行release旧值再retain新值,所有 实现都是这个顺序(CC上有相关资料)
5.copy,setter方法进行Copy操作,与retain处理流程一样,先旧值release,再Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。
6.nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级(我是这么理解的...)。
二、(一共九题)
1.络编程中设计并发服务器,使用多进程与多线程,请问有什么区别?
a)答1)进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。2)线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
2.数组a[N],存放了1至N-1个数,其中某个数重复一次。写一个函数,找出被重复的数字.时间复杂度必须为o(N)函数原型:int do_dup(int a[],int N)
答:int do_dup(int a[],intN)
{
int sum= 0;
int sum2;
for(int i=0;i
{
Sum+=a[i];
}
Sum2 = (1+N-1)*N/2;
Return (sum-sum2);
}
3.一语句实现x是否为2的若干次幂的判断
答:
方法1)int i = 512;
cout <<
boolalpha<< ((i & (i - 1)) ?false : true) << endl;//位与为0,则表示是2的若干次幂
方法2)return (x>>N==1);
4.unsigned int
intvert(unsigned int x,int p,intn)实现对x的进行转换,p为起始转化位,n为需要转换的长度,假设起始点在右边.如x=0b00010001,p=4,n=3转换后x=0b0110 0001
答:unsigned int intvert(unsigned int x,int p,int n)//假定p=4,n=3
unsigned int _t = 0;unsignedint _a = 1;
for(int i = 0; i
++i)//循环的目的主要是-t_t |=_a;
_a = _a<<1;
_t =_t<
x ^=_t;
return x;
5.什么是预编译,何时需要预编译?
答:预编译又称为预处理,是做些代码文本的替换工作。处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段,主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。c编译系统在对程序进行通常的编译之前,先进行预处理。c提供的预处理功能主要有以下三种:1)宏定义2)文件包含3)条件编译。
6.下述三个有什么区别?
char * const p;
char const * p
const char *p
char * const p; //常量指针,p的值不可以修改
char const * p;//指向常量的指针,指向的常量值不可以改
const char *p;//和char const *p
7.解释下列输出结果
char str1[] ="abc";char str2[] = "abc";const char str3[] ="abc";
const char str4[] ="abc";const char *str5 = "abc";
const char *str6 ="abc";char *str7 = "abc";char *str8 = "abc";
cout << (str1 == str2 )<< endl;cout << ( str3 == str4 )<< endl;
cout << ( str5 == str6)<< endl;cout << ( str7 == str8 )<< endl;
结果是:0 0 1 1
解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域。
8.以下代码中的两个sizeof用法有问题吗?[C易]
void UpperCase( char str[] )
//将str中的小写字母转换成大写字母
for( size_t i=0;i
if( 'a'<=str[i]&&str[i]<='z'str[i] -= ('a'-'A' );
char str[] ="aBcDe";
cout << "str字符长度为: "<
UpperCase( str );
cout << str<
答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。
注意:数组名作为函数参数时,退化为指针.数组名作为sizeof()参数时,数组名不退化,因为sizeof不是函数.
三、(一共十六题)
1.objective-c中是所有对象间的交互是如何实现的?(深圳皆凯科技有限公司笔试题)
2.如何将产品进行多语言发布?
3.objective-c中是如何实现线程同步的?
4.编写函数_memmove说明如下:实现C语言库函数memmove的功能:将一块缓冲区中的数据移动到另一块缓冲区中。可能有重复。
5.什么叫数据结构?(面试顺风快递iPhone开发)
6.编程中,保存数据有哪几种方式?
7.Sizeof与strlen的区别和联系?
答案:
1.sizeof操作符的结果类型是size_t,它在头文件中typedef为unsignedint类型。该类型保证能容纳实现所建立的最大对象的字节大小。
2.sizeof是算符,strlen是函数。
3.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的。
4.数组做sizeof的参数不退化,传递给strlen就退化为指针了。
5.大部分编译程序在编译的时候就把sizeof计算过了是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因
char str[20]="0123456789";//str是编译期大小已经固定的数组
int a=strlen(str); //a=10;//strlen()在运行起确定
int b=sizeof(str); //而b=20;//sizeof()在编译期确定
6.strlen的结果要在运行的时候才能计算出来,是用来计算字符串的实际长度,不是类型占内存的大小。
7.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。
char c;
sizeof c;//变量名可以不加括弧
8.当适用了于一个结构类型时或变量,sizeof返回实际的大小,当适用一静态地空间数组,sizeof归还全部数组的尺寸。sizeof操作符不能返回动态地被分派了的数组或外部的数组的尺寸
9.数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:
fun(char [8])
fun(char [])
都等价于fun(char *)
在C++里参数传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小
如果想在函数内知道数组的大小,需要这样做:
进入函数后用memcpy拷贝出来,长度由另一个形参传进去
fun(unsiged char *p1, int len)
{
unsigned char* buf = new unsigned char[len+1]
memcpy(buf, p1, len);
}
我们能常在用到sizeof和strlen的时候,通常是计算字符串数组的长度
看了上面的详细解释,发现两者的使用还是有区别的,从这个例子可以看得很清楚:
har
str[11]="0123456789";//注意这里str大小因该大于等于11,应考虑'\0'在内,否则编译器会报错
int a=strlen(str); //a=10;
>>>> strlen计算字符串的长度,以结束符0x00为字符串结束。
int b=sizeof(str); //而b=11;
>>>> sizeof计算的则是分配的数组str[11]所占的内存空间的大小,不受里面存储的内容改变。
上面是对静态数组处理的结果,如果是对指针,结果就不一样了
char* ss ="0123456789";
sizeof(ss)结果4===》ss是指向字符串常量的字符指针,sizeof获得的是一个指针的之所占的空间,应该是长整型的,所以是4
sizeof(*ss)结果1===》*ss是第一个字符其实就是获得了字符串的第一位'0'所占的内存空间,是char类型的,占了1位strlen(ss)= 10 >>>>如果要获得这个字符串的长度,则一定要使用strlen另外,下面的方法可以用于确定该静态数组可以容纳元素的个数int a[3]={1,2,3};
cout << sizeof a/sizeof ( typeid( a[0] ).name() );
8.什么是抽象类?抽象类有什么作用?能实例化吗?
9.用Objective-C写冒泡法.
10.考察对@interface和@property的理解?
11.IPhone开发中控制类有什么作用?
12.线程中有哪些函数?写出来。
13.有没有写过自定义的控件?
14.调用一个类的静态方法需不需要release?
15.do-while与while-do的区别?
16.写出几个死循环?
答案:while(1){}
或者do{}while(1)
再或者for(;1;){}
还有goto的
Loop:
…
goto Loop;
四、(一共十八题)
1.ObjC中,与alloc语义相反的方法是dealloc还是release?与retain语义相反的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?
答案::alloc与dealloc语意相反,alloc是创建变量,dealloc是释放变量。retain对应release,retain保留一个对象。调用之后,变量的计数加1。或许不是很明显,在这有例为证:
(void) setName : (NSString*)name {
[name retain];
[myname release];
myname = name;
}
我们来解释一下:设想,用户在调用这个函数的时候,他注意了内存的管理,所以他小心的写了如下代码:
NSString * newname =[[NSString alloc] initWithString: @"John"];
[aClass setName: newname];
[newname release];
我们来看一看newname的计数是怎么变化的。首先,它被alloc,count = 1;然后,在setName中,它被retain,count = 2;最后,用户自己释放newname,count = 1,myname指向了newname。这也解释了为什么需要调用[myname release]。我们需要在给myname赋新值的时候,释放掉以前老的变量。retain之后直接dealloc对象计数器没有释放。alloc需要与release配对使用,因为alloc这个函数调用之后,变量的计数加1。所以在调用alloc之后,一定要调用对应的release。另外,在release一个变量之后,他的值仍然有效,所以最好是后面紧接着再var = nil。
在一个对象的方法里面:
2.self.name =“object”;和name=”object”有什么不同吗?
答案::self.name = "object"会调用对象的setName()方法,name = "object"会直接把object赋值给当前对象的name属性。
[backcolor=transparent][backcolor=transparent]
3.这段代码有什么问题吗:
[backcolor=transparent]@implementationPerson
[backcolor=transparent]-(void)setAge:(int)newAge {
[backcolor=transparent]self.age= newAge;
[backcolor=transparent]}
[backcolor=transparent]@end
答案:会进入死循环。
4.什么是retain count?
答案::引用计数(ref count或者retain count)。对象的内部保存一个数字,表示被引用的次数。例如,某个对象被两个指针所指向(引用)那么它的retain count为2。需要销毁对象的时候,不直接调用dealloc,而是调用release。release会让retain count减1,只有retain count等于0,系统才会调用dealloc真正销毁这个对象。
5.以下每行代码执行后,person对象的retain count分别是多少
Person *person = [[Personalloc] init]; count 1
[person retain]; count 2
[person release];count 1
[person release];retaincount = 1;
6.为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?
答案:会引起循环引用。
7.定义属性时,什么情况使用copy,assign,和retain。
答案:assign用于简单数据类型,如NSInteger,double,bool,retain和copy用户对象,copy用于当a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy的方式,a和b各自有自己的内存,就可以解决这个问题。retain会使计数器加一,也可以解决assign的问题。另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:
if (property != newValue){[property release];property = [newValue retain];}
8.Autorelease的对象是在什么时候被release的?
答案:autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。对于每一个Runloop,系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object(就是autorelease的对象)会被release。那什么是一个Runloop呢?一个UI事件,Timer call,delegate call,都会是一个新的Runloop。那什么是一个Runloop呢?一个UI事件,Timer call,delegate call,都会是一个新的Runloop。
9.这段代码有什么问题,如何修改
for (int i = 0; i
{
NSString *string = @”Abc”;
string = [stringlowercaseString];
string = [stringstringByAppendingString:@"xyz"];
NSLog(@“%@”, string);
}答案::会内存泄露,
修改:
for(int i = 0; i<1000;i++){
NSAutoreleasePool * pool1 =[[NSAutoreleasePool alloc] init];
NSString *string =@"Abc";
string = [stringlowercaseString];
string = [stringstringByAppendingString:@"xyz"];
NSLog(@"%@",string);
[pool1 drain];
}
你的解决方法效率低,没必要在每个循环都建立autorelease pool。在循环外面建一个就行了。
NSAutoreleasePool * pool1 =[[NSAutoreleasePool alloc] init];
for(int i = 0;i<1000;i++){
NSString *string =@"Abc";
string = [stringlowercaseString];
string = [stringstringByAppendingString:@"xyz"];
NSLog(@"%@",string);
}
[pool1 release];//[pool1
drain];效果相同,但我更喜欢release,看起来传统一点
10.autorelease和垃圾回收机制(gc)有什么关系?答案::不懂
11.IPhone OS有没有垃圾回收(gc)?没有
12.什么是Notification?答案:观察者模式,controller向defaultNotificationCenter添加自己的notification,其他类注册这个notification就可以收到通知,这些类可以在收到通知时做自己的操作(多观察者默认随机顺序发通知给观察者们,而且每个观察者都要等当前的某个观察者的操作做完才能轮到他来操作,可以用NotificationQueue的方式安排观察者的反应顺序,也可以在添加观察者中设定反映时间,取消观察需要在viewDidUnload跟dealloc中都要注销)。参考链接:http://useyourloaf.com/blog/2010/6/6/delegation-or-notification.html
13.什么时候用delegate,什么时候用Notification?答案:delegate针对one-to-one关系,并且reciever可以返回值给sender,notification可以针对one-to-one/many/none,reciever无法返回值给sender.所以,delegate用于sender希望接受到reciever的某个功能反馈值,notification用于通知多个object某个事件。
14.什么是KVC和KVO?答案:KVC(Key-Value-Coding)内部的实现:一个对象在调用setValue的时候,
(1)首先根据方法名找到运行方法的时候所需要的环境参数。
(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。
(3)再直接查找得来的具体的方法实现。KVO(Key-Value-Observing):当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名。
15.Notification和KVO有什么不同?答:不知道
16.KVO在ObjC中是怎么实现的?答:不知道
17.ViewController的loadView, viewDidLoad, viewDidUnload分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?
答案:viewDidLoad在view从nib文件初始化时调用,loadView在controller的view为nil时调用。此方法在编程实现view时调用,view控制器默认会注册memory warning notification,当view controller的任何view没有用的时候,viewDidUnload会被调用,在这里实现将retain的view release,如果是retain的IBOutlet view属性则不要在这里release,IBOutlet会负责release。
18.ViewController的didReceiveMemoryWarning是在什么时候被调用的?默认的操作是什么?答案:默认调用[superdidReceiveMemoryWarning]
五、一共七题
1.Objective-C的内存管理方式, NSAutoreleasePool的作用
2.写一个retain方式声名属性的setter方法
3.Objective-C与C的区别有哪些
4.列出你常用的几个设计模式,列出如何在Objective-C中实现与应用
5.drawRect,
lasyoutSubViews的区别
6.列举Cocoa中常用的几种多线程实现,并谈谈多线程安全问题的几种解决方案,什么地方会用到多线程
7.Socket连接相关库,TCP,UDP的连接方法,HTTP的几种常用方式
六、一共四题
1.用Objective-C写冒泡法
2.Cocoa函数库的使用
3.考察对线程的理解
4.考察对MVC的理解?模型—视图—控制器
七、一共九题
1.Objective-C内部的实现
2.CALayer和View的关系
3.http协议,tcp/ip
4.UITableView的那些元素是可以自定义的?
5.c语言的,定义变量,比如int,在什么情况下,其最大值是不同的
6.比较32位平台和64位平台不同
7.iPhone app为什么会被打回来,如何避免??
8.为啥离开团队?
八、一共十题
1.为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain?
会导致循环引用。
2.有如下一个类定义
interface MyClass : NSObject
{}
@property(retain) NSString *myProp;
@end
请完成myProp属性的set方法:
-(void)setMyProp:(NSString*)aProp
{
if(myProp!=aPtrop)
[myProp release]
myProp=[aProp retain ]
}
3.写出下面程序段的输出结果
NSString *aStr = [[[NSString alloc]
initWithString:@”Hello World”] autoRelease];
NSMutableArray *aArray = [NSMutableArray array];
[aArray addObject:aStr];
NSLog(@”ref=%d”, [aStr retainCount])
4.简述Notification的工作机制。
5.有一个UIView对象aView,当前大小为全屏。请编写代码实现如下效果:将aView的宽和高各缩小为原来一半,中心点仍在屏幕中心,并在缩小的同时实现渐隐。
6.写出下面程序段的输出结果
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"a stringvalue" forKey:@"akey"];
NSLog(@"%@", [dict objectForKey:@"akey"]);
[dict release];
7.@class关键字有什么作用
8.不使用继承,为NSStirng类添加新方法myPrint。
9.写出下面程序段的输出结果
NSArray array = [NSArrayarrayWithObjects:@"one",@"two",@"three",nil];
NSLog(@"%@", [array objectAtIndex:1]);
NSLog(@"%@", [array objectAtIndex:3]);