关于原子的内存管理stm32f4库函数版原子有几点想请教一下

查看: 6197|回复: 0
uc/os-ii操作系统的内存管理实现实例--很受用!
& &&&每次 温故uc/os-ii操作系统的源码都有收获,经典的东西就是经典;uc/os-ii曾经把我搞得好累,但是经过一段时间摸索之后发现只要有正确的学习方法,学好uc/os-ii并不难,同时基于uc/os-ii操作系统的应用程序开发也不难。关于嵌入式系统内存管理的方法应该不少,原子的内存管理教程就有两个例程,一个是“特大号数组”型,一个是动态分配型,两者都使用了malloc()函数。而uc/os-ii操作系统的内存管理实现原理很精妙没有使用malloc()函数,主要是考虑该函数申请内存的时间不确定性。可以说,通过该例程就能理解uc/os-ii操作系统的内存管理实现原理。笔者认为通过实例学习,理解uc/os-ii操作系统的原理是个不错的选择。
& & 本实验基于PC机在DOS环境下模拟。
/*设计一个有3个任务的应用程序,这3个任务分别是Mytask Youtask Hertask。在应用程序中创建一个动态内存分区,该分区有8个内存块,每个内存块的长度是6字节。应用程序的任务Youtask Hertask都在任务运行后请求一个内存块.随后就释放它;任务MYTASK也在任务运行后请求一个内存块,但是要在任务MYTASK运行6次后,才释放它所申请的内存块。为了了解内存分区变化的情况,编写代码来观察分区头指针和已被使用内存块的个数*/
#include &INCLUDES.h&
#define&&TASK_STK_SIZE& && &&&512& && & /* 任务堆栈长度*/& && && && &
OS_STK& && &&&StartTaskStk[TASK_STK_SIZE];& & /*定义任务堆栈区 */
OS_STK& && &&&MyTaskStk[TASK_STK_SIZE];
OS_STK& && &&&YouTaskStk[TASK_STK_SIZE];
OS_STK& && &&&HerTaskStk[TASK_STK_SIZE];
char *s1= &Mytask&&&;
char *s2= &Youtask &;
char *s3= &Hertask &;
INT8U&&y=0;& &//字符显示位置&&
INT8U&&Times=0;
OS_MEM& && &&&*IntB& && &/*定义内存控制块指针,创建一个内存分区时,返回值就是它 */
INT8U& && && &IntPart[8][6];&&/*划分一个具有8个内存块,每个内存块长度是6的内存分区 */
INT8U& && && &*IntBlkP& && &/*定义内存块指针,确定内存分区中首个内存块的指针&&*/
OS_MEM_DATA MemI& &/*存放内存分区的状态信息 */
void&&StartTask(void *data);& && && && && &/* 声明起始任务&&*/
void&&MyTask(void *data);& && && && && && &/* 声明任务& && &*/
void&&YouTask(void *data);& && && && && &&&/* 声明任务& && &*/
void&&HerTask(void *data);& && && && && &&&/* 声明任务& && &*/
********************************************************************
*& && && && &&&MAIN主函数
**********************************************************************
void&&main (void)
& & OSInit();& && && && && &/* 初始化uC/OS-II& && && && && && && & */
& & PC_DOSSaveReturn();& && & /* 保存DOS环境& &&&*/
& & PC_VectSet(uCOS, OSCtxSw);& &&&/* 安装uC/OS-II的中断 */
& & IntBuffer=OSMemCreate(IntPart,8,6,&err);& & /*创建动态内存区&&*/
& & OSTaskCreate(StartTask, (void *)0, &StartTaskStk[TASK_STK_SIZE - 1], 0);
& & OSStart();& && && && & /* 启动多任务管理& &*/
***********************************************************
*& && && && && & STARTUP TASK:主要功能就是创建3个任务
***********************************************************
void&&StartTask(void *pdata)
#if OS_CRITICAL_METHOD == 3& && &/* Allocate storage for CPU status register,实际应用中该部分可省略 */
& & OS_CPU_SR&&cpu_
& & INT16S& && &&&& && && & /*用于退出的建*/
& & pdata =& && && & /* Prevent compiler warning& && && && && &&&*/
& & OS_ENTER_CRITICAL();
& & PC_VectSet(0x08, OSTickISR);& && &/* 安装时钟中断向量 , */
& & PC_SetTickRate(OS_TICKS_PER_SEC);& &/* 设置时钟频率 */
& & OS_EXIT_CRITICAL();
& & OSStatInit();& && &&&/* 初始化统计任务& &*/
& & OSTaskCreate(MyTask, (void *)0, &MyTaskStk[TASK_STK_SIZE - 1], 3);
& & OSTaskCreate(YouTask, (void *)0, &YouTaskStk[TASK_STK_SIZE - 1], 4);
& & OSTaskCreate(HerTask, (void *)0, &HerTaskStk[TASK_STK_SIZE - 1], 5);
& & for (;;) {
& & //如果恩下ESC键,则退出UC/OS-II
& && &&&if (PC_GetKey(&key) == TRUE) {& &/* See if key has been pressed& &&&*/
& && && && &if (key == 0x1B) {& && & /* Yes, see if it's the ESCAPE key& & */
& && && && && & PC_DOSReturn();& & /* Return to DOS& && & */
& && && && &}
& && &&&OSTimeDlyHMSM(0, 0, 3, 0);& &/* Wait 3s,在这里创建完StartTask任务为什么不挂起自己?& && &*/
/*--------------------MyTask任务-------------------------*/
void MyTask(void *pdata)
#if OS_CRITICAL_METHOD == 3& && & /* Allocate storage for CPU status register */
& & OS_CPU_SR&&cpu_
for( ; ; )
PC_DispStr(10,++y,s1,DISP_BGND_BLACK+DISP_FGND_WHITE);&&/*&++y&执行一次就换一次行&&*/
IntBlkPtr=OSMemGet(& &/*请求内存分区的内存块的指针 */
& && && && && &&&IntBuffer, /*这个参数就指明了要获取的内存块属于哪个内存分区 */&&
& && && && && &&&&err);& && &
& &OSMemQuery(& && &&&/*查询内存控制块信息 */
& && & & &&&IntBuffer,& &&&/*带查询内存控制块指针 */
&MemInfo);
sprintf(s,&%0x&,MemInfo.OSFreeList);&&/*显示头指针 */
PC_DispStr(30,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);
sprintf(s,&%d&,MemInfo.OSNUsed);&&/*显示已用的内存块数目 */
PC_DispStr(40,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);
if(Times&4)&&/*0-1-2-3-4-5;Times==6时该条件语句为真 */
OSMemPut(IntBuffer,IntBlkPtr);& &/* 进入第6次就释放已经使用过的内存块&&*/
OSTimeDlyHMSM(0,0,1,0);&&//等待2s
/*-------------------------------Youtask-------------------------------------*/
void YouTask(void *pdata)
#if OS_CRITICAL_METHOD == 3& && && && && && && && && && &&&/* Allocate storage for CPU status register */
& & OS_CPU_SR&&cpu_
for( ; ; )
PC_DispStr(10,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE);
IntBlkPtr=OSMemGet(& && && && &//请求内存块
& && && && && &&&IntBuffer,& &//内存分区的指针
& && && && && &&&&err);& && & //错误信息
& &OSMemQuery(& && &&&//查询内存控制块信息
& && & & &&&IntBuffer,& &&&//带查询内存控制块指针
&MemInfo);
sprintf(s,&%0x&,MemInfo.OSFreeList);&&//显示头指针
PC_DispStr(30,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);
sprintf(s,&%d&,MemInfo.OSNUsed);&&//显示已用的内存块数目
PC_DispStr(40,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);
OSMemPut( IntBuffer, IntBlkPtr );
OSTimeDlyHMSM(0,0,2,0);&&//等待2s
/*-------------------------------Hertask-------------------------------------*/
void HerTask(void *pdata)
#if OS_CRITICAL_METHOD == 3& && &/* Allocate storage for CPU status register */
& & OS_CPU_SR&&cpu_
for( ; ; )
PC_DispStr(10,++y,s3,DISP_BGND_BLACK+DISP_FGND_WHITE);
IntBlkPtr=OSMemGet(& && && && &//请求内存块
& && && && && &&&IntBuffer,& &//内存分区的指针
& && && && && &&&&err);& && & //错误信息
& &OSMemQuery(& && &&&//查询内存控制块信息
& && & & &&&IntBuffer,& &&&//带查询内存控制块指针
&MemInfo);
sprintf(s,&%0x&,MemInfo.OSFreeList);&&//显示头指针
PC_DispStr(30,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);
sprintf(s,&%d&,MemInfo.OSNUsed);&&//显示已用的内存块数目
PC_DispStr(40,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);
IntBuffer,
OSTimeDlyHMSM(0,0,1,0);&&//等待2s
通过本例的实验现象能深刻理解内存管理函数的本质;现象分析如下:
y(行)& & 显示内容:& && & 显示头指针OSFreeList:& &&&显示已用的内存块数目OSNUsed:
1,& && &&&MyTask& && && && &&&504& && && && && && && && & 1
2,& && &&&YouTask& && && && & 50A& && && && && && && && & 2
3,& && &&&HerTask& && && && & 50A& && && && && && && && & 2
4,& && &&&MyTask& && && && &&&50A& && && && && && && && & 2
5,& && &&&HerTask& && && && & 510& && && && && && && && & 3
6,& && &&&MyTask& && && && &&&510& && && && && && && && & 3
7,& && &&&YouTask& && && && & 516& && && && && && && && & 4
8,& && &&&HerTask& && && && & 516& && && && && && && && & 4
9,& && &&&MyTask& && && && &&&516& && && && && && && && & 4
10,& && & HerTask& && && && & 51C& && && && && && && && & 5
11,& && & MyTask& && && && &&&51C& && && && && && && && & 5
12,& && & YouTask& && && && & 522& && && && && && && && & 6
13,& && & HerTask& && && && & 522& && && && && && && && & 6
14,& && & MyTask& && && && &&&522& && && && && && && && & 6
15,& && & MyTask& && && && &&&522& && && && && && && && & 6
通过上表可以看出:1,“显示头指针OSFreeList”的数据很有规律,即都是以6为单位递增,这是因为在创建内存控制块时就定义了每个内存块的长度是6个字节,所以就是以6为单位递增,(0x504+0x6)==0x50A;
(0x50A+0x6)==0x510,(0x510+0x6)==0x516,等等; 2,第2行中,因为YouTask任务请求一个内存块之后就立即释放了,所以在第3个任务(HerTask任务)中,HerTask任务申请到的还是50A指针指向的内存块,同样在本任务中及时释放了内存块,实际上此时系统只占用504内存块,所以到第4个任务MyTask 任务执行时,还是显示已用2个内存块,不过这时MyTask 任务已经占用了两个内存块,因为此时MyTask 任务还没有释放内存块;3,当if(Times&4) 时 (0-1-2-3-4-5;Times==6时该条件语句为真)MyTask 任务得到一个内存块就立即释放了该内存块,所以就一直会显示已用6个内存块,指针值停留在0x522处,不会再递增了;4,由此现象得知:a),本例中申请到的8个内存块是连续的地址空间;b),系统在初始化时,就初始化了一个空的任务控制块链表,每个任务控制块的有效数据为空,但是结点指针都有所指;当系统申请一个内存分区时,空闲任务控制块就会减1,释放了就加1;c),整个空闲链表是不是一个大的连续内存空间,还不知道,我觉得应该看OSInit()源码。
*/& && && && && && && && && && && && && && && && && && && && && && && && && && && && && && &&&& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &
Powered by查看: 916|回复: 6
原子兄的内存管理碎片问题?
主题帖子精华
中级会员, 积分 446, 距离下一级还需 54 积分
在线时间1 小时
原子兄,有个问题请教:
& 关于你的那个内存malloc和free这两个函数功能会出现碎片么?有碎片管理么?
会生成内存碎片,没做碎片管理,做的话就很复杂了,STM32就不适合了
创新超越梦想,拼搏创造奇迹....
主题帖子精华
在线时间1096 小时
会生成内存碎片,没做碎片管理,做的话就很复杂了,STM32就不适合了
开往春天的手扶拖拉机
主题帖子精华
金牌会员, 积分 2507, 距离下一级还需 493 积分
在线时间643 小时
之前用的iar自动链接的dlmalloc,貌似很好用,不过就是编译后有8k的代码
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
主题帖子精华
中级会员, 积分 446, 距离下一级还需 54 积分
在线时间1 小时
回复【3楼】zuozhongkai:
---------------------------------
那用的话&应该没有什么危险吧,只是浪费了点内存&是不?
创新超越梦想,拼搏创造奇迹....
主题帖子精华
中级会员, 积分 446, 距离下一级还需 54 积分
在线时间1 小时
回复【2楼】ianhom:
---------------------------------
写个教程嘛...
创新超越梦想,拼搏创造奇迹....
主题帖子精华
金牌会员, 积分 2507, 距离下一级还需 493 积分
在线时间643 小时
回复【5楼】废墟崛起之厦:
---------------------------------
我用的是iar的环境,iar中如果你想用标准库中的malloc,只需要在文件中包含stdlib.h,然后调用malloc就会自动链接到dlmalloc中的malloc函数,也看了下iar的说明文档,貌似用iar&for&arm&6.x版本之后就使用了dlmalloc。如果不想用这个dlmalloc就自己写一个malloc,free,relloc函数就可以重定向,我的情况就是因为这个dlmalloc中编译完有8k的大小,加上我工程的代码超过了flash容量,所以就没用dlmalloc,使用了自己写的malloc。
至于dlmalloc有没有碎片管理,可以百度一下,网上有源码和详解。
KEIL的环境我没有使用过,所以不知道在keil环境下使用的库函数是什么(keil有个microLIB),这里的malloc是否满足你的要求我也不是很清楚。如果dlmalloc满足你的要求,你可以加入dlmalloc的源码到你的工程中进行重定向试试看。
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
主题帖子精华
金牌会员, 积分 1517, 距离下一级还需 1483 积分
在线时间637 小时
没有MMU的芯片无法进行碎片整理,只能由使用者自己去留意。并把紧急任务需要的内存固定或先分配好。
Powered by当前位置: >>
ios面试整理
1.Objective-C中,与alloc语义相反的方法是dealloc还是release?与retain语义 相反的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是 dealloc还是release,为什么? 答:alloc与dealloc语意相反,alloc是创建变量,dealloc是释放变。 retain对应 release,retain保留
一个对象。调用之后,变量的计数加1。或许不是很明显,在 这有例为证: . - (void) setName : (NSString*) 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赋新值的时候, 释放掉以前老的 [name retain]; [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]@implementation Person . [backcolor=transparent]- (void)setAge:(int)newAge { . [backcolor=transparent]self.age = newA . [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 = [[Person alloc] init]; count 1 . [person retain]; count 2 . [person release];count 1 . [person release];retain count = 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) { . . . } 8.的对象是在什么时候被release的? 答: autorelease实际上只是把对release的调用延迟了, 对于每一个Autorelease, 系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该 [property release]; property = [newValue retain]; 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 & someLargeN i++) . { . NSString *string = @”Abc”; . string = [string lowercaseString]; . string = [string stringByAppendingString:@&xyz&]; . NSLog(@“%@”, string); . } 答:会内存泄露, . for(int i = 0; i&1000;i++){ . NSAutoreleasePool * pool1 = [[NSAutoreleasePool alloc] init]; . NSString *string = @&Abc&; . string = [string lowercaseString]; . string = [string stringByAppendingString:@&xyz&]; . NSLog(@&%@&,string); . [pool1 drain]; . } 10.autorelease和垃圾回收机制(gc)有什么关系? 答:不懂 11.IPhone OS有没有垃圾回收(gc)? 没有 12.什么是Notification? 答:观察者模式,controller向defaultNotificationCenter添加自己的notification, 其他类注册这个notification就可以收到通知, 这些类可以在收到通知时做自己的 操作 (多观察者默认随机顺序发通知给观察者们, 而且每个观察者都要等当前的 某个观察者的操作做完才能轮到他来操作, 可以用NotificationQueue的方式安排 观察者的反应顺序,也可以在添加观察者中设定反映时间,取消观察需要在 viewDidUnload 跟dealloc中都要注销)。参考链接: /blog//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在Objective-C中是怎么实现的? 答:不知道 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 是在什么时候被调用的? 默认的操作是什么? 答:默认调用[super didReceiveMemoryWarning] iOS 开发:iPhone 面试题解答1.main() { inta[5]={}; int *ptr=(int*)( a+1); printf(&%d%d&,*(a+1),*(ptr-1)); } 答:25 *(a+1)就是 a[1],*(ptr-1)就是 a[4]执行结果是 2,5a+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. 以下为 WindowsNT 下的 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(constNSString * inputString) { is amaintest\n&; } -main(void) { NSString&; NSString*aString = [NSStringstringWithString:@&%@&getNSString(a)]; NSLog(@&%@\n&aString); } 最后问输出的字符串:NULLoutput 在函数返回后, 内存已经被开释。 对比一下 iOS 开发。 4.用预处理指令#define 声明一个常数,用以表明 1 年中有多少秒(马虎闰年问 题) #define SECONDS_PER_YEAR(60 * 60 * 24 *365)UL 我在这想看到几件事 情: ?; #define 语法的基础学问(例如:不能以分号结束,括号的使用,等等) ?;懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年 中有多少秒而不是计算出实际的值,是更清晰而没有代价的。 ?;意识到这个表达式将使一个 16 位机的整型数溢出-因此要用到长整型符号 L 告 诉编译器这个常数是的长整型数。 ?;如果你在你的表达式中用到 UL(表示无符号长整型) ,那么你有了一个好的起 点。记住,第一印象很严重。 写一个&标准&宏 MIN,这个宏输入两个参数并返回较小的一个。 #defineMIN(AB) ( (A) &= (B) ? (A) :(B))这个测试是为下面的目的而设的: ?;标识#define 在宏中应用的基础学问。这是很严重的,因为直到嵌入(inline)操 作符变为标准 C 的一局部,iphone。宏是方便产生嵌入代码的唯一方法,对付 嵌入式编制来说,为了能达到要求的性能,嵌入代码经常是必须的方法。 ?;三重条件操作符的学问。 这个操作符存在 C 言语中的原因是它使得编译器能产 生比 if-then-else 更优化的代码,了解这个用法是很严重的。 ?; 懂得在宏中小心地把参数用括号括起来 ?; 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什 么事?]\ least = MIN(*p++b); 结果是: ((*p++) &= (b) ? (*p++) : (*p++)) 这个表达式会产生副作用,指针 p 会作三次++自增操作。 5.写一个委托的 interface @protocolMyD @interface MyClass:NSObject { id &MyDelegate& } // 委托方法 @protocolMyDelegate - (void)didJobs:(NSArray*) @end6.写一个 NSString 类的完成 +(id)initWithCString:(constchar *)nullTerminatedCStringencoding:(NSStringEncoding) + (id) stringWithCString:(const char*)nullTerminatedCString encoding: (NSStringEncoding)encoding { NSString* 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 * } +(void)thisIsAStaticM -(void)thisIsAnInstsome kind ofceM @end @interface Controller(private) (void)thisIsAPrivateM @end @private 可以用来修饰私有变量 在 Objective\C 中,所有实例变量默认都是私有的,所有实例方法默认都是公有 的 9.关键字 const 有什么含意?修饰类呢?static 的作用用于类呢?还有 extern c 的 作用 const 意味着&只读&,下面的声明都是什么意思? const int *a; int * int const *前两个的作用是一样,a 是一个常整型数。第三个意味着 a 是一个指向常整型数 的指针(也就是,整型数是不可修改的,但指针可以) 。第四个意思 a 是一个指 向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可 修改的) 。最后一个意味着 a 是一个指向常整型数的常指针(也就是说,指针指 向的整型数是不可修改的,同时指针也是不可修改的) 。 结论: ?;关键字 const 的作用是为给读你代码的人传达非常有用的信息,实际上,声明 一个参数为常量是为了告诉了用户这个参数的应用目的。如果 你曾花很多时间清理其它人留下的渣滓,你就会很快学会感谢这点多余的信息。 Windows Mobile。 (当然,懂得用 const 的程序员很少会留下的渣滓让别人来清 理的。 ) ?;通过给优化器一些附加的信息,使用关键字 const 也许能产生更紧凑的代码。 ?;合理地使用关键字 const 可以使编译器很自然地保护那些不理想被改变的参 数,防止其被无意的代码修改。简而言之,这样可以减少 insect 的出现。 (1)欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量 时,通常须要对它进行初始化,因为以后就没无机会再去改变它了; (2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指定为 const; (3)在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函 数外部不能改变其值; (4)对付类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不 能修改类的成员变量; (5)对付类的成员函数,有时期必须指定其返回值为 const 类型,以使得其返 回值不为“左值” 关键字 volatile 有什么含意?并给出三个不同的例子。 。 一个定义为 volatile 的变量是说这变量可能会被意想不到地改变,这样,编译器 就不会去假设这个变量的值了。 精确地说就是, 优化器在用到这个变量时必须每 次都小心地重新读取这个变量的值, 面试题解答。 而不是使用保存在寄存器里的 备份。下面是 volatile 变量的几个例子: ?;并行设备的硬件寄存器(如:状态寄存器) ?; 一个中断服务子程序中会访问到的非主动变量(Non-automaticvariables) ?; 多线程应用中被几个任务共享的变量 ?;一个参数既可以是 const 还可以是 volatile 吗?解释为什么。 ?; 一个指针可以是 volatile 吗?解释为什么。 下 面是答案: ?;是的。一个例子是只读的状态寄存器。它是 volatile 因为它可能被意想不到地 改变。它是 const 因为程序不应该试图去修改它。 ?;是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个 drink stationrier 的指针时。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 言语头文件(假设为 cExamplifierle.h)时,需进 行下列处理: extern &C& { #include &cExamplifierle.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 显然,头文件中的编译宏“#ifndef__INCvxWorksh、#define __INCvxWorksh、 #endif” 的作用 是防止该头文件被重复引用。 11.#import 跟#include 的区别@class 呢? @class 一般用于头文件中须要声明该类的某个实例变量的时期用到, m 文件 在 中还是须要使用#import而#import 比起#include 的好处就是不会引起交叉编译 12.MVC 模式的理解 MVC 设计模式思索三种对象:模型对象、视图对象、和控制器对象。模型对象 代表特别的学问和专业技能, 它们负责保有应用程序的数据和定义操作数据的逻 辑。 视图对象知道如何显示应用程序的模型数据, 而且可能允许用户对其进行编 辑。控制器对象是应用程序的视图对象和模型对象之间的调解者。 13.线程与进程的区别和联系? 进程和线程都是由操作编制所体会的程序运转的基础单元, 编制使用该基础单元 完成编制对应用的并发性。 程和线程的主要差别在于它们是不同的操作编制资源管理方式。 进程有独立的地 址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是 一个进程中的不同执行途径。 线程有自己的堆栈和局部变量, 但线程之间没有单 独的地址空间, 一个线程死掉就等于整个进程死掉, 所以多进程的程序要比多线 程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。你看 Windows Mobile,Windows Mobil。 但对付一些要求同时进行并且又要共享某些变量的并发 操作,只能用线程,不能用进程。 14.列举几种进程的同步机制,并比较其优缺点。你知道面试题。 答案:原子操作信号量机制自旋锁管程,会合,分布式编制 进程之间通信的途径 答案:共享存储编制消息传递编制管道:以文件编制为基础 进 程死锁的原因 答案:资源竞争及进程推进秩序作歹死锁的 4 个必要条 件 答案:互斥、请求保持、不可剥夺、环路死锁的处理 答案:鸵鸟策略、预防策略、制止策略、检测与解除死锁 15.堆和栈的区别 管理方式: 对付栈来讲, 是由编译器主动管理, 无需我们手工控制; 对付堆来说, 开释劳动由程序员控制,容易产生 memory leak。 申请大小: 栈:在 Windows 下栈是向低地址扩展的数据布局,是一块连续的内存的区域。 这句话的意思是栈顶的地址和栈的最大容量是编制预先规定好的,在 WINDOWS 下,栈的大小是 2M(也有的说是 1M,总之是一个编译时就确定的 常数) ,其他手机开发。如果申请的空间突出栈的糟粕空间时,将提示 overflow。 因此,能从栈获得的空间较小。 堆:堆是向高地址扩展的数据布局,是不连续的内存区域。这是由于编制是用链 表来存储的空闲内存地址的, 自然是不连续的, 而链表的遍历方向是由低地址向 高地址。堆的大小受限于计算机编制中有效的虚拟内存。由此可见,堆获得的空 间比较灵活,也比较大。 碎片问题:对付堆来讲,频繁的 new/delete 势必会造成内存空间的不连续,从 而造成大量的碎片,使程序效率降低。对付栈来讲,则不会存在这个问题,因为 栈是先进后出的队列, 他们是如此的一一对应, 以至于永远都不可能有一个内存 块从栈中间弹出 分配方式:堆都是动态分配的,没有静态分配的堆。栈有 2 种分配方式:静态分 配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由 alloca 函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译 器进行开释,对于 Android 开发。无需我们手工完成。 分配效率:栈是机器编制提供的数据布局,计算机会在底层对栈提供接济:分配 专门的寄存器存放栈的地址, 压栈出栈都有专门的指令执行, 这就决定了栈的效 率比较高。堆则是 C/C++函数库提供的,它的机制是很纷乱的。 16.什么是键-值键途径是什么 模型的本质是通过一个简单的键(通常是个字符串)来指定的。视图和控制器通 过键来查找相应的属性值。 在一个给定的实体中, 同一个属性的所有值具有相同 的数据类型。键-值编码技术用于进行这样的查找―它是一种间接访问对象属性 的机制。 键途径是一个由用点作分隔符的键组成的字符串, 用于指定一个连接在一起的对 象本质序列。第一个键的 本质是由先前的本质决定的, 接下来每个键的值也是绝对付其前面的本质。 键途 径使您可以以独立于模型 完成的方式指定相关 对象的本质。通过键途径,您可以指定对象图中的一个任 意深度的途径,使其指向相 关对象的特定属性。 For examplifierle the key pathpostingdress.streetwould get the value of the postingdress property from thereceivingobject as well asn determine thestreet property relative to the postingdress object. 17.c 和 obj-c 如何混用 1)obj-c 的编译器处理后缀为 m 的文件时,可以识别 obj-c 和 c 的代码,处理 mm 文件可以识别 obj-ccc++代码, 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 的东西,包括#importcocoa 的。面试题解答。完成文件中,即类的完成 代码中可以使用 obj-c 的东西,可以 import 只是后缀是 mm。 如果模块以函数完成,那么头文件要按 c 的格式声明函数,完成文件中,c++函 数外部可以用 obj-c,但后缀还是 mm 或 m。 总结: 只要 cpp 文件和 cppinclude 的文件中不包括 obj-c 的东西就可以用了, cpp 混用 obj-c 的关键是使用接口, iOS 开发。 而不能直接使用完成代码, 实际上 cpp 混用的是 obj-c 编译后的 o 文件,这个东西其实是无差别的,所以可以用。obj-c 的编译器接济 cpp. 18.目标-动作机制 目标是动作消息的接收者。一个控件,其他手机开发。或者更为常见的是它的单 元,以插座变量(参见&插座变量&局部) 的形式保有其动作消息的目标。动作是控件发送给目标的消息, 或者从目标的角度看, 它是目标为了响应动作而 完成的方法。 程序须要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制。 19.cocoa touch 框架 iPhone OS 应用程序的基础 CocoaTouch 框架重用了许多 Mac 编制的成熟 模式, 但是它更多地专注于触摸的接口和优化。UIKit 为您提供了在 iPhone OS 上完成图形,事件驱动程序的基础工具,其建立在和 Mac OS X 中一样的 Foundation 框架上,包括文件处理,网络,字符串操作等。 Cocoa Touch 具有和 iPhone 用户接口一致的特殊设计。有了 UIKit,您可以使 用 iPhone OS 上的独特的图形接口控件,按钮,以及全屏视图的效用,您还可 以使用加快仪和多点触摸手势来控制您的应用。 各色俱全的框架 除了 UIKit 外, CocoaTouch 包括了创建世界一流 iPhone 应 用程序须要的所有框架,从三维图形,到专业音效,听听开发。以至提供设备访 问 API 以控制摄像头,或通过 GPS 获知当前位置。Cocoa Touch 既包括只须 要几行代码就可以完成全部任务的强大的 Objective-C 框架, 也在须要时提供基 础的 C 言语 API 来直接访问编制。这些框架包括: Core Animation 通过 CoreAnimation,您就可以通过一个基于组合独立图层的简单的编程模型 来创建丰富的用户体验。Core Audio Core Audio 是播放,你知道 ios。处理和录制音频的专业技术,com 的人员能够 轻松为您的应用程序添加强大的音频效用。 Core Data 提供了一个面向对象的数据管理解决计划, 它易于使用和理解, 以至可处理任何 应用或大或小的数据模型。 效用列表:框架分类 下面是 Cocoa Touch 中一小局部可用的框架: 音频和视频 Core Audio OpenAL Media Libreast supportry AV Foundation 数据管理 Core Data SQLite 图形和动画 Core Animation OpenGL ES Quartz 2D 网络/li& Bonjour WebKit BSD Sockets 用户应用 Address Book Core Location Map Kit Store Kit 20.objc 的内存管理 ?如果您通过分配和初始化(比如[[MyClass alloc] init])的方式来创建对象, Windows Phone。您就拥有这个对象,须要负责该对象的开释。这个规则在使 用 NSObject 的便利方法 new 时也同样适用。 ?如果您拷贝一个对象,您也拥有拷贝得到的对象,事实上 Windows Phone。须 要负责该对象的开释。 ?如果您保持一个对象, 您就局部拥有这个对象, 须要在不再使用时开释该对象。 反过去, ?如果您从其它对象那里接收到一个对象,则您不拥有该对象,也不应该开释它 (这个规则有少数的例外,在参考文档中有显式的说明) 。 21.主动开释池是什么如何劳动 当您向一个对象发送一个 autorelease 消息时, Cocoa 就会将该对象的一个引用 放入到最新的主动开释池。 它仍然是个正当的对象, 因此主动开释池定义的作用 域内的其它对象可以向它发送消息。 当程序执行到作用域结束的位置时, 主动开 释池就会被开释,池中的所有对象也就被开释。1.ojc-c 是通过一种&referring counting&(引用计数)的方式来管理内存的对象在开 始分配内存(alloc)的时期引用计数为一以后每当碰到有 copyretain 的时期引用 计数都会加一每当碰到 release 和 autorelease 的时期引用计数就会减一如果此 对象的计数变为了 0 就会被编制销毁. 2. NSAutoreleasePool 就是用来做引用计数的管理劳动的这个东西一般不用你 管的. 3.autorelease 和 release 没 什 么 区 别 只 是 引 用 计 数 减 一 的 时 机 不 同 而 已 autorelease 会在对象的使用真正结束的时期才做引用计数减一.22.类工厂方法是什么 类工厂方法的完成是为了向客户提供方便,它们将分配和初始化合在一个步骤 中,返回被创建的对象,并进行主动开释处理。这些方法的形式是+ (type)className...(其中 className 不包括任何前缀) 。工厂方法可能不仅仅 为了方便使用。 它们不但可以将分配和初始化合在一起, 还可以为初始化过程提 供对象的分配信息。 类工厂方法的另一个目的是使类 (比如 NSWorkspace) 提供单件实例。 虽然 init... 方法可以确认一个类在每次程序运转过程只存在一个实例, 但它须要首先分配一 个“生的”实例,然后还必须开释该实例。你看解答。工厂 方法则可以制止为可 能没有用的对象盲目分配内存。 23.单件实例是什么 Foundation 和 ApplicationKit 框架中的一些类只允许创建单件对象,即这些类 在 当 前 进 程 中 的 唯 一 实 例 。 举 例 来 说 , NSFileMsome kind ofager 和 NSWorkspace 类在使用时都是基于进程进行单件对象的实例化。当向这些类请 求实例的时期,它们会向您传递单一实例的一个引用,如果该实例还不存在,则 首先进行实例的分配和初始化。 单件对象充当控制中心的角色,负责指引或调 解类的各种服务。如果类在概念上唯有一个实例(比如 NSWorkspace) ,就应 该产生 一个单件实例,而不是多个实例;如果将来某一天可能有多个实例,您 可 以使用单件实例机制,而不是工厂方法或函数。 24.动态绑定―在运转时确定要调用的方法 动态绑定将调用方法的确定也推迟到运转时。 在编译时, 方法的调用并不和代码 绑定在一起,唯有在消实发送出来之后,才确定被调用的代码。通过动态类型和 动态绑定技术, 您的代码每次执行都可以得到不同的结果。 运转时因子负责确定 消息的接收者和被调用的方法。 运转时的消息分发机制为动态绑定提供接济。 当 您向一个动态类型确定了的对象发送消息时,运转环境编制会通过接收者的 isa 指针定位对象的类, 并以此为起点确定被调用的方法, 方法和消息是动态绑定的。 而且,您不必在 Objective-C 代码中做任何劳动,就可以主动获取动态绑定的好 处。您在每次发送消息时, 特别是当消息的接收者是动态类型已经确定的对象时,你知道 iOS 开发。动态 绑定就会例行而透明地发生。 25.obj-c 的优缺点 objc 优点: 1)Cateogies 2)Posing 3) 动态识别 4)指标计算 5)弹性讯息传递 6) 不是一个过度纷乱的 C 衍生言语 7) Objective-C 与 C++可混合编程 缺点: 1)不支援命名空g 2)不接济运算符重载 3)不接济多重继承 4)使用动态运转时类型,所有的方法都是函数调用,所以很多编译时优化方法 都用不到。iPhone。 (如内联函数等) ,性能低劣。 26.sprintfstrcpymemcpy 使用上有什么要注意的地方 strcpy 是一个字符串拷贝的函数,它的函数原型为 strcpy(char*dst const char *src); 将 src 开始的一段字符串拷贝到 dst 开始的内存中去,结束的标志符号为'\0',由 于拷贝的长度不是由我们自己控制的, 所以这个字符串拷贝很容易出错。 具备字 符串拷贝效用的函数有 memcpy,这是一个内存拷贝函数,它的函数原型为 memcpy(char *dst const char* src unsigned intlen); 将长度为 len 的一段内存,从 src 拷贝到 dst 中去,这个函数的长度可控。但是 会有内存叠加的问题。 sprintf 是格式化函数。 将一段数据通过特定的格式,格式化到一个字符串缓冲区 中去。 sprintf 格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲 区的大小,Android 开发。造成溢出。 27. 用变量 a 给出下面的定义 a) 一个整型数(Aninteger) b)一 个指向整型数的指针( A pointer to some kind ofinteger) c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to some kind ofintege)r d)一个有 10 个整型数的数组( An assortment of 10integers) e) 一个有 10 个指针的数组, 该指针是指向一个整型数的。 An assortment of 10 ( pointers tointegers) f) 一个指向有 10 个整型数数组的指针( A pointer to some kind of assortment of 10integers) g) 一个指向函数的指针, 该函数有一个整型参数并返回一个整型数 pointer to (A a function that takessome kind of integer as some kind of argument some kind ofd returns some kind ofinteger) h) 一个有 10 个指针的数组, 该指针指向一个函数, 该函数有一个整型参数并返 回一个整型数( An assortment of tenpointers to functions t hat take some kind of integer argument some kind ofd return some kind of integer) 答 案是: a) // Aninteger b) int *a; // A pointer to some kind ofinteger c) int **a; // A pointer to a pointer to some kind ofinteger d) int a[10]; // An assortment of 10integers e) int *a[10]; // An assortment of 10 pointers tointegers f) int (*a)[10]; // A pointer to some kind of assortment of 10integers g) int (*a)(int); // A pointer to a function athattakes some kind of integer argument some kind ofd returns some kind ofinteger h) int (*a[10])(int); // An assortment of 10 pointers tofunctionsthat take some kind of integer argument some kind ofdreturn some kind of integer 28.repostingwrite,repostingonly,assign,retain,copy,nonatomic 属性的作 用 @property 是一个属性访问声明,扩号内接济以下几个属性: 1,getter=getterName,setter=setterName,设置 setter 与 getter 的方法名 2,repostingwriterepostingonly,设置可供访问级别 2,assign,看看 iOS 开发。setter 方法直接赋值,不进行 任何 retain 操作,为 了解决原类型与环循引用问题 3,retain,setter 方法对参数进行 release 旧值再 retain 新值,所有完成都是这 个秩序(CC 上有相关原料) 4,copy,setter 方法进行 Copy 操作,与 retain 处理流程一样,先旧值 release, 再 Copy 出新的对象, retainCount 为 1。 这是为了减少对上下文的依赖而引入的 机制。 5,nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意, 如果不加此属性, 则默认是两个访问方法都为原子型事务访问。 锁被加到所属对 象实例级(我是这么理解的...)。 @来完成实际代码 1Objective-C 外部的完成 2CALayer 和 View 的关系 3 http 协议,tcp/ip4 UITableView 的那些元素是可以自定义的?5 c 言语的,定义变量,比如 int,在 什么情况下, 其最大值是不同的 6 比较 32 位平台和 64 位平台不同 7 iphone app 为什么会被打回来,如何制止??8 为啥离开团队? 1.针对第一个问题,可以看看下面的教程 Object c 研究的比较深入的教程 第 6 章写的加倍好 KVO/KVC 完成机理分析 2.CALayer 和 View 的关系 一个 UIView 包括 CALayer 树,CALayer 是一个数据模型,听说 iPhone。包括 了一些用于显示的对象,但本身不用于显示。 CALayer 相当于 photoshop 的一个层, 很多动画可以通过设置 CALayer 来完成。 据说有人用 CALayer 显示图片来播放视频。 Coresome kind ofimation 应该是用 CAlayer 来完成各种动画。 这里有篇博文,介绍的还可以 1.objc 是扩充 C 的面向对象,开发 mac osx 的编程语言。 2.objc 中的减号与加号 ①减号表示一个函数、或者方法或者消息的开始(在一个类的实例上被调用和实 施) ②加号表示其他的函数可以直接调用这个类中的方法, 而不用创建这个类的实例 3.NS 开发包 乔布斯的 NextStep 公司缩写,现今 mac os 使用 NS 这套函数库 4.#import 作用如同#include,用于声明头文件。 5.nil 表示空指针,相当于 java 的 null 6.objc 中使用字符串,前面要加上&@&,是因为在前面加上&符号&,编译器在编 译的时候会在程序中给你留出位置,这样才能保证这个字符串不会丢失。(@是 把 C 的字符串转成 NSString 的一个简写) 7.开发 objc 类,需要创建一个头文件和一个实现文件 ①头文件(.h):包含类的实例变量的名称和类型、 描述方法参数和返回值类型的方 法签名; ②实现文件(.m):包含这些方法的实现代码, 以及对别的类不可见的, 仅与实现本 身相关的局部变量的声明和使用。 8.九宫格解法原理;(右上解法) 左出右写入、右出左写入、上出下写入、下出上写入、重排置下; 9.iphone 应用程序的项目基本结构 classes:里面存放 object-c 类源代码文件(可以创建子文件夹来组织代码); other sources:存放除 objective-c 类之外的源代码文件; resources: 包含应用程序中的非代码文件(因为应用程序只能在自己的沙盒中运 行,不然找不到); Frameworks:特殊的库,可以存放库、框架、图像、声音等资源; Products:包含项目在编译时生成的应用程序(xxx.app); 10.Info.plist 文件里的 bundle identifier(束标识符) 它是应用程序的唯一标识符,要始终配置,命名格式为:顶级 Internet 域+.+公 司名称+.+应用名称; 11.一个在代码里对 nib 中对象(UILabel、UITextField 等)的引用被称为一个插座 变量(outlet) ,用关键字 IBOutlet 标明(在头文件里);能够被 nib 中对象调用的 方法称为动作(action) ,用关键字 IBAction 标明(在实现文件里)。 12.在实现某个动作或是对象后要对这个动作或是对象后要使用 release 释放内 存。 13.IBOutlet 输出口 使用关键字 IBOutlet 来声明实例变量,并通过这个实例变量来引用 nib 中 的对象; 14.-(IBAction)doSomething:(id)sender 控制某个对象执行某项动作 通过关键字 IBAction 来声明,通过 IBAction 告诉 interface Builder,此方法是一个操作,且可以被某个控件触发;通常 这个操作 接受一个参数,该参数被定义为 id,名称被指定为 sender.(当需要传参数的时候 就通过 sender 来传递,当不需要传参数的时候 sender 可以不写的); 15.@property (retain , nonatomic) UILable textA retain 是通知编译器向分配给此属性的对象发送一个保留(retain)消息, 确保属性 的实例变量在被使用过程中不会被从内存中删除; nonatomic 是 创建一个互斥访问,避免读和写不同步(非原子性访问); 通过这个属性声明访问来提高执行的效率;(原子性好比如我们去银行存钱,存 进去的时候银行账户就会同时增加相应的数额,有一面失败就都回到原来的状 态) ; 16.内存管理理解 ①:程序 A 里有一段内存被成功申请完成之后,内存计数器就从 0 变为 1(这个 过程是 alloc); ②:然后程序 B 里也要使用这个内存,那么内存计数器从 1 变为 2 (这个过程是 retain); ③:紧接着程序 A 不需要这个内存了,那么程序 A 就把这个内存计数器减 1 (这个过程是 release); ④:当系统发现这个内存计数器变为 0,那么就调用内存回收程序把这段内存回 收(这个过程是 dealloc); 17.objc 使用消息机制来调用方法,消息就是一个类或者对象可以执行的动作消 息表达式:[对象或者类名字 方法名字:参数序列]; 对象或者类名字:接收器,是消息的接收者; 方法名字:参数序列:要发送的消息(要执行的动作); 5、如何引用一个已经定义过的全局变量? 答:可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式 来引用某个在头文件中声明的全局变变量, 假定你将那个变量写错了, 那么在编 译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编 译期间不会报错,而在连接期间报错。 5、extern关键字的用法? 答: extern可以置于变量或者函数前, 以表示变量或者函数的定义在别的文件中, 提示编译器遇到此变量和函数时在其他模块中寻找其定义。另外,extern也可用 来进行链接指定。 6、语句for( ;1 ;)有什么问题?它是什么意思? 答:和while(1)相同都是死循环。 7、请写出下列代码的输出内容 #include &stdio.h& b=a++; c=++a; main() { int a,b,c,d; a=10;d=10*a++; ? return 0; ? }printf( &b, d, %d, c, a: %d, %d 答:10,12,120 ,13&,b,c,d, a);6、bool在C中没有C++中才有? 答:C语言里面没有bool(布尔)类型C++里面才引入bool类型 C语言里面用数值0表示假,非0整数表示真(一般是1) 7、转义字符 9、全局变量和局部变量可以同名吗? 答:能,局部会屏蔽全局。要用全局变量,需要使用 &:: & 。局部变量可以与全 局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全 局变量 1、#import 和#include 的区别 @class?(10 分) 答:防止重复包含 @class 类的前置声明 会在下边的类中使用某个类的对象 2、property 的属性 retain,copy,assign 的含义分别是什么?有什么区别?将 其转化为 get/set 方法怎么做?(10 分) 答: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]; readwrite,readonly,assign,retain,copy,nonatomic 属性的作用 @property 是 一 个 属 性 访 问 声 明 , 扩 号 内 支 持 以 下 几 个 属 性 : ? 1 , getter=getterName,setter=setterName,设置 setter 与 getter 的方法名?2, readwrite,readonly,设置可供访问级别?2,assign,setter 方法直接赋值,不进 行任何 retain 操作,为了解决原类型与环循引用问题?3,retain,setter 方法对 参数进行 release 旧值再 retain 新值, 所有实现都是这个顺序(CC 上有相关资料) ?4, copy, setter 方法进行 Copy 操作, retain 处理流程一样, 与 先旧值 release, 再 Copy 出新的对象,retainCount 为 1。这是为了减少对上下文的依赖而引入 的机制。?5,nonatomic,非原子性访问,不加同步,多线程并发访问会提高性 能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被 加到所属对象实例级(我是这么理解的...)。 3、请说明 self 的作用? 在一个对象的方法里面:self.name = “object” 和?name =”object”?有什么不同 ; 吗? (10 分) 答:self.name = &object&:会调用对象的 setName()方法; name = &object&:会直接把 object 赋值给当前对象的 name 属性 。 4、请简述 self.name = nil 的机制,以及与[name release]的区别?(10 分) self.name = //使用 nil 参数调用 setName:方法生成的访问器将自动释放以前的 name 对象 5、这段代码有什么问题,如何修改?(10 分) for (int i = 0; i & someLargeN i++) { NSString *string = @”Abc”; string = [string lowercaseString]; string = [string stringByAppendingString:@&xyz&]; NSLog(@“%@”, string); } 答:会内存泄露, for(int i = 0; i&1000;i++) { NSAutoreleasePool * pool1 = [[NSAutoreleasePool alloc] init]; NSString *string = @&Abc&;? string = [string lowercaseString];? string = [string stringByAppendingString:@&xyz&]; NSLog(@&%@&,string); [pool1 drain];? } 6、请介绍 iPhone 开发中的内存管理机制,并说明 autorelease 和垃圾回收机制 (gc)有什么关系?(10 分) 。 答:对象是在什么时候被 release 的? autorelease 和垃圾回收机制(gc)有什么关系? 答: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。 7、请简要说明 viewDidLoad 和 viewDidUnload 何时调用,及注意的事项(10 分) 。 分析: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 。 8、在 iPhone 的开发中用到很多代理模式,请简述代理模式带来的好处?继承 与代理模式的区别和简要认知?写出一个自定义委托类(10 分) 。 9、 委托是什么?委托的 property 声明用什么属性?写出一个自定义委托 (5 分) 答:@protocol SimpleProtocol -(void)doSomething:(NSString *) @end @interface SimpleClass:NSObject& SimpleProtocol &{ } @end @implementation SimpleClass -(void) doSomething:(NSString *)str { NSLog(str); } @end 9、请简述 iPhone 数据持久化的种方法?(10 分) 答:属性列表、对象归档、iPhone 的嵌入式关系数据库(SQLite3)和拷久性工具 Core Data。 10、实例化一个 UITableView 对象,要求写出关键语句?(10 分) 答:UITableView *my = [[UITableView alloc] initWithFrame:&(CGRect)frame& style:&(UITableViewStyle)style&]; my.delegate = my.dataSource = 首先需要分配空间 设置表格类型 然后需要设置两个必须的委托对象。 12、使用 sql 语句查询出省名以湖开头,邮编为 436001 所在的市区?(5 分) (表名及字段名自定义) 1. 写出程序的输出结果 main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf(&%d,%d&,*(a+1),*(ptr-1)); } 2,5 2. 用预处理指令#define 声明一个常数,用以表明 1 年中有多少秒(忽略闰年 问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 3.obj-c 有多重继承么?如果没有什么替代方法? cocoa 中所有的类都是 NSObject 的子类,多继承在这里是用 protocol 委托代 理来实现的。你不用去考虑繁琐的多继承,虚基类的概念。 4. obj-c 有私有方法么?私有变量呢? objective-c - 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整 的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私 有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私 有方法 @interface Controller : NSObject { NSString * } + (void)thisIsAStaticM - (void)thisIsAnInstanceM @end @interface Controller (private) (void)thisIsAPrivateM @end @private可以用来修饰私有变量 在 Objective\C 中,所有实例变量默认都是私有的,所有实例方法默认都 是公 有的 5. static 关键字的作用,在 Objective-C 中的用法。 (1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量 的内存只被分配一次,?因此其值在下次调用时仍维持上次的值; ?(2)在模块 内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访 问; ?(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函 数的使用范围被限制在声明?它的模块内; ?(4)在类中的 static 成员变量属 于整个类所拥有,对类的所有对象只有一份拷贝; ?(5)在类中的 static 成员 函数属于整个类所拥有, 这个函数不接收 this 指针, 因而只能访问类的 static 成 员变量。 6. MVC 模式的理解 这个模式认为,程序不论简单或复杂,从结构上看,都可以分成三层。 1)最上面的一层,是直接面向最终用户的&视图层&(View)。它是提供给用户 的操作界面,是程序的外壳。 2)最底下的一层,是核心的&数据层&(Model),也就是程序需要操作的数据或 信息。 3)中间的一层,就是&控制层&(Controller),它负责根据用户从&视图层&输入 的指令,选取&数据层&中的数据,然后对其进行相应的操作,产生最终结果。 这三层是紧密联系在一起的, 但又是互相独立的, 每一层内部的变化不影响其他 层。每一层都对外提供接口(Interface),供上面一层调用。这样一来,软件就 可以实现模块化, 修改外观或者变更数据都不用修改其他层, 大大方便了维护和 升级。 7. 假定输入的字符串中只包含字母和*号。编写函数 fun,功能是,除了中间和 尾部的*号外, 将字符串中其他*号全部删除。编写时,不用 c 的其他函数。 例:*****A*BC*DEF*G**** void fun (char *a) { int j=0; char *p=a; while (*p=='*')p++; while (*p){ a[j++]=*p; 结果为:A*BC*DEF*G**** p++; } a[j]=0; } 1.这段代码有什么问题吗: @implementation Person - (void)setAge:(int)newAge { self.age = newA } 死循环 2. 以下为WindowsNT下的32位C++程序,请计算sizeof的值 void Func ( char str[100]) { sizeof( str ) =4 } void *p = malloc( 100 ); sizeof ( p ) = 4 3. 用变量a给出下面的定义 a) 一个整型 b)一 个指向整型数的指针 c)一个指向指针的的指针,它指向的指针是指向一个整型数 d)一个有10个整型数的数组 e) 一个有10个指针的数组,该指针是指向一个整型数的 f) 一个指向有10个整型数数组的指针 g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数 h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返 回一个整型数 a) b) int *a; c) int **a; d) int a[10] e) int *a[10]; f) int (*a)[10]; g) int (*a)(int); h) int (*a[10])(int);4.截取字符串”20|“ 中 ‘|’字符前面及后面的数据,分 别输出它们 NSString *str = &20|&; NSRange range = [str rangeOfString:@&|&]; int location = range. NSString *str1 = [str substringToIndex:location]; NSString *str2 = [str substringFromIndex:location+1]; 5, 给定一个字符串, 输出本字符串中只出现一次并且最靠前的那个字符的位置? 比如&abaccddeeef& 则是b,输出2 int find(char *_str) { char *p = _ int i = 1; while (*p) { char *temp = _ while (*temp) { if ((*p == *temp)&&(p != temp)) { } temp++; if (*temp == 0) { } } i++; p++; } return -1; } #include #include #include &stdio.h& &stdlib.h& &string.h&int find_char(const char* str) { static int pos[256]; const unsigned char* p = (const unsigned char*) int i = 0; if( (!str) || (!(*str)) ) return -1; memset(pos,-1,sizeof(pos)); while(*p){ if(pos[*p] == -1){ pos[*p] = p-(const unsigned char*) }else{ pos[*p] = -2; } p++; } for(i=0;i&sizeof(pos)/sizeof(pos[0]);i++){ if(pos[i]&=0)return pos[i]; } return -1; } int main() { const char* p = &abaccddeeef&; int pos = find_char(p); printf(&%d, it is '%c'\n&,pos,pos!=-1?p[pos]:' ');p = &abcdefghijklmnopqrstuvwxyz & &abcdefghijklmnopqrstu wxyz &; pos = find_char(p); printf(&%d, it is '%c'\n&,pos,pos!=-1?p[pos]:' '); return 0; } 1. objective-c中的数字对象都有哪些,简述它们与基本数据类型的区别是什 么? 在OC中NSNumber是数字对象,可以进行拆装箱操作! //将int转为NSNumber NSNumber *num = [NSNumber numberWithInt:123]; //得到一个int int testNum = [num intValue]; 2.用NSLog函数输出一个浮点类型,结果四舍五入,并保留一位小数 NSLog(@”%0.1f”,4.4324); 3.objective-c中的词典对象、可变词典对象是哪个,初始化一个含有两个键值对 的可变词典对象,并动态的添加和删除一条记录,输出第一条记录. 词典NSDictionary,可变词典NSMutableDictionary, //初始化一个可变词典,带有2个键值对 NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@&value1&,@&key1&,@&value2&,@&key2&,nil]; //添加 [dic setObject:@&value3& forKey:@&key3&]; //删除 [dic removeObjectForKey:@&key3&]; //获取(按key获取) [dic objectForKey:@&key1&]; 4.获取项目根路径,并在其下创建一个名称为userData的目录。 // 获取根路径 NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDom ainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:]; // 创建文件系统管理器 NSFileManager *fileManager = [[NSFileManager alloc] init]; // 判断userData目录是否存在 if(![fileManager fileExistsAtPath:[NSString stringWithFormat:@&%@/userData&, documentsDirectory]]) { // 不存在,创建一个userData目录 [fileManager createDirectoryAtPath:[NSString stringWithFormat:@&%@/userData&, documentsDirectory]withIntermediateDirectories:false attributes:nil error:nil]; } 如果你在mac上测试一定是在你得文稿下边,但装到手机上就不一样了,每一个 iPhone应用都会有一个自己独立得documents,所以不会冲突! 5.ViewController 的viewDidLoad,viewWillAppear,viewDidUnload,dealloc 分别是在什么时候调用,在自定义ViewController的时候这几个函数里面应该做 什么工作? (1)、viewDidLoad 此方法只有当view从nib文件初始化的时候才被调用 例如动 态在view添加一个按钮等 (2)、viewDidUnload当系统内存吃紧的时候会调用该方法,在该方法中将所有 IBOutlet(无论是property还是实例变量)置为nil(系统release view时已经将其 release掉了)在该方法中释放其他与view有关的对象、其他在运行时创建(但 非系统必须)的对象、在viewDidLoad中被创建的对象、缓存数据等 release对 象后,将对象置为nil(IBOutlet只需要将其置为nil,系统release view时已经将 其release掉了) 这里需要说明Unload在3.0之后被广泛使用,现在已经很少用 didReceiveMemoryWarning, (3)、dealloc方法,viewDidUnload和dealloc方法没有关联,dealloc还是继续做它 该做的事情 流程应该是这样: (loadView/nib文件)来加载view到内存 --&viewDidLoad函数进一步初始化这些 view --&内存不足时,调用viewDidUnload函数释放views --&当需要使用view时 有回到第一步 如此循环 (4)、 viewWillAppear方法,视图即将过渡到屏幕上时调用,(一般在返回需要刷新页 面时,我都选择使用代理,所以很少用到) (5)、viewWillDisappear方法,这个A-&B之后,A在B之后的操作 6.怎样自动生成属性的获取方法和设置方法 合成存取器 7.do-while 与 while-do 的区别? do-while 先执行循环体,然后判断条件,如果条件判断为ture,则继续执行循环 体,如果判断为false,则不执行循环体 while-do 是先判断条件是否正确,若正确则执行循环体,若不正确则不执行循 环体。 所以 do-while 至少循环一次,而 while-do 有可能一次也不循环。 8.用 C 语言,求 2 到 100 内的所有素数和。 #include &stdio.h& int isPrime(int n) { for(i=2;i*i&=n;i++) if(n%i==0) return 0; return 1; } int main() { int i,sum=0; for(i=2;i&100;i++) if( isPrime(i)) sum+=i; printf(&%5d&,sum); //求素数,这是最经典的算法代码。建议记住 return 0 ; } int isPrime(int n) { for(i=2;i&=n/2;i++) { if(n%i==0) } if(i&n/2) return 1; else return 0; } 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?原因如下: 而 指针加1要根据指针类型加上一 a是长度为5的int数组指 但是prt与(&a+1)类型是&a是数组指针, 其类型为 int (*)[5];?定的值,不同类型的指针+1之后增加的大小不同。? 针, 所以要加 5*sizeof(int)? 不一样的(这点很重要)? 所以ptr实际是a[5]?所以prt-1只会减去sizeof(int*) a是数组首地址,也就是a[0]的地a,&a的地址是一样的,但意思不一样? 址,&a是对象(数组)首地址,? 是下一个对象的地址,即a[5].a+1是数组下一元素的地址,即a[1],&a+12. 以下为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&; } -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 ?我在这想看到几件事 情: ??; #define 语法的基本知识 (例如: 不能以分号结束, 括号的使用, 等等) ??; 懂得预处理器将为你计算常数表达式的值, 因此, 直接写出你是如何计算一年中 有多少秒而不是计算出实际的值,是更清晰而没有代价的。? ??; 意识到这个表 达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常 数是的长整型数。 ??; 如果你在你的表达式中用到UL(表示无符号长整型), 那么你有了一个好的起点。记住,第一印象很重要。 写一个&?标准&宏MIN ,这个宏输入两个参数并返回较小的一个。 ?#define MIN(A,B) ((A) &= (B) ? (A) : (B)) ?这?个测试是为下面的目的而 设的: ??; ?标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌 入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方?法,?对 于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。 ??; ?三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产 生比 if-then-else 更优化的代码,了解这个用法是很重要的。? ???; 懂得在宏 中小心地把参数用括号括起来 ??; 我也用这个问题开始讨论宏的副作用,例 如:当你写下面的代码时会发生什么事? ? ?least = MIN(*p++, b); 结果是:?((*p++) &= (b) ? (*p++) : (*p++))?这个表达式会产生副作用,指针p会 作三次++自增操作。 5.写一个委托的 interface @protocol MyD @interface MyClass: NSObject { id &MyDelegate& } // 委托方法@protocol MyDelegate - (void)didJobs:(NSArray *) @end 6. 写一个NSString类的实现 + (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding) + (id) stringWithCString: (const char*)nullTerminatedCString ? ?{? NSString * 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的原则就是一个对象只暴露有用的东西. 如果没有了 encoding: (NSStringEncoding)encoding 私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个 私有方法 @interface Controller : NSObject { NSString * } + (void)thisIsAStaticM - (void)thisIsAnInstanceM @end @interface Controller (private) (void)thisIsAPrivateM @end @private可以用来修饰私有变量 在Objective\C中,所有实例变量默认都是私有的,所有实例方法默认都 是公有 的 9.关键字const有什么含意?修饰类呢?static的作 用,用于类呢?还有extern c的 作用 const 意味着&只读&,下面的声明都是什么意思? ? ? ? const int *a; ?int * ?int 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 吗?解释为什么。 ??下 面是答案: ??; 是的。一个例子是只读 的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序 不应该试图去修改它。 ??; 是的。尽管这并不很常见。一个例子是当一个中服务 子程序修该一个指向一个buffer的指针时。 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.为什么标准头文件都有类似以下的结构? ? __INCvxWorksh ? &C& { ? #endif ? #define __INCvxWorksh ? /*...*/ ? #ifdef __cplusplus ? #ifndef #ifdef __cplusplus ? } ? #endif ? extern#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++函数库提供的,它的机制是很复杂}

我要回帖

更多关于 stm32f4库函数版原子 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信