Objective_C 面试题一

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 ) = ?

这题很常见了,Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof ( p ) 都为4。

3.还是考指针,不过我对cocoa的代码还是不太熟悉
大概是这样的
-(void)*getNSString(const NSString * inputString)
{
inputString = @"This is a main test\n";
 return ;}
-main(void)
{ NSString
*a=@"Main";
 NSString *aString = [NSString stringWithString:@"%@",getNSString(a)];

 NSLog(@"%@\n", aString); }
最后问输出的字符串:NULL,output在函数返回后,内存已经被释放。
4.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B)
((A) <= (B) ? (A) : (B))

5.写一个委托的interface
@protocol MyDelegate;
@interface MyClass: NSObject
{    id <MyDelegate> delegate; }
//
委托方法
@protocol MyDelegate
- (void)didJobs:(NSArray *)args;
@end

6.写一个NSString类的实现
+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;
+ (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 -类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法
@interface Controller : NSObject { NSString *something; }
+ (void)thisIsAStaticMethod;
- (void)thisIsAnInstanceMethod;
@end
@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end
@private可以用来修饰私有变量
在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的

9.关键字const有什么含意?修饰类呢?static的作用,用于类呢?还有extern c的作用
const意味着"只读",下面的声明都是什么意思?
 const int a;
 int const a;
 const int *a;
 int * const a;
 int const * a const;
前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

 

结论:
•;关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果
 你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清
 理的。)
 •; 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
 •; 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。 
(1)欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初
 始化,因为以后就没有机会再去改变它了;
 (2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指
 定为 const;
 (3)在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
 (4)对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量;
 (5)对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左值”。

 

关键字volatile有什么含意?并给出三个不同的例子。
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到
 这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 

 

•;并行设备的硬件寄存器(如:状态寄存器)
 •; 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) •; 多线程应用中被几个任务共享的变量
•;一个参数既可以是const还可以是volatile吗?解释为什么。
 •; 一个指针可以是volatile 吗?解释为什么。

 下面是答案:

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 类型。

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 __cplusplus
    extern "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.线程与进程的区别和联系?
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

14.列举几种进程的同步机制,并比较其优缺点。
答案:  原子操作 信号量机制    自旋锁    管程,会合,分布式系统
 进程之间通信的途径
答案:共享存储系统消息传递系统管道:以文件系统为基础
 进程死锁的原因
答案:资源竞争及进程推进顺序非法
 死锁的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框架
iPhoneOS应用程序的基础 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
提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。

是会有内存叠加的问题。
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 a function that takes an integer as an argument  and 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 to an integer 
 c) int **a; // A pointer to a pointer to an integer 
 d) int a[10]; // An array of 10 integers 
 e) int *a[10]; // An array of 10 pointers to integers 
 f) int (*a)[10]; // A pointer to an array of 10 integers 
 g) int (*a)(int); // A pointer to a function a that  takes an integer argument and returns an integer 
 h) int (*a[10])(int); // An array of 10 pointers to functions  that take an integer argument and return an integer

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值