2016-08-29 18:38:48 qq_35757299 阅读数 483
  • 宏定义与预处理、函数函数库-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8171 人正在学习 去看看 朱有鹏

在工程的Supporting Files文件夹中,有一个main函数

int main(int argc, char * argv[]) {
    @autoreleasepool {

        /**
         *  argc,argv是C标准main函数的参数,直接传递给UIApplicationMain进行相关处理即可;
         principalClassName:指定应用程序类,该类必须是UIApplication类或其子类。如果为nil,则用UIApplication类作为默认值
         delegateClassName:指定应用程序类的代理类,该类必须遵循UIApplicationDelegate协议,此函数会根据principalClassName创建UIApplication对象,根据delegateClassName创建一个delegate对象,并将该delegate对象赋值给UIApplication对象中的delegate属性。UIApplication对象会依次给delegate对象发送不同的消息,接着会创建应用程序的main runloop(事件循环),进行事件的处理(首先会调用delegate对象的 application:didFinishLaunchingWithOptions : ) 程序正常退出时这个函数才返回。
         UIApplication 对象管理事件循环和高层的应用行为
         应用委托是应用的核心,该对象与UIApplication对象联合起来负责对应用的初始化过程、状态迁移过程和很多高层的应用事件进行处理

         */
     return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

AppDelegate是应用程序委托对象,它继承于UIResponder,并且遵循了UIApplicationDelegate协议

#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

应用程序的生命周期

/**
 *  
 *  作为应用程序的委托对象,AppDelegate类在应用的生命周期的不同阶段会回调不同的方法
 *
 *  此类本身没有任何功能代码,它的作用就是实现了UIAplication和iOS操作系统之间的协议。该协议的方法就对应UIAplication在操作系统中的各种状态。
 *  iOS应用的五种状态:
 *  Not Runing(非运行状态)   应用没有运行或者被系统终止
 *  Inactive(前台非活跃状态) 应用进入前台状态,但是还不能接收事件处理
 *  Active(前台活跃状态)     应用进入前台状态,能接收事件处理
 *  Background(后台状态)    应用进入后台状态,依然能够执行代码。如果有可以执行的代码,就会执行代码,如果没有可以执行的代码或者将可执行的代码执行完毕,应用就会马上进入挂起状态。
 *  Suspended(挂起状态)     应用进入一种‘冷冻’状态,不能执行代码。如果系统的内存不足,应用会被终止。
 */

以下是遵循方法UIApplicationDelegate协议实现的方法

//应用启动并进行初始化的时候会调用该方法,并发出通知。在这个阶段会初始化根视图控制器。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"应用启动并进行初始化");
    return YES; 
} 
//应用从活跃状态到非活跃状态时调用该方法,并发出通知。这个阶段可以保存UI状态。
- (void)applicationWillResignActive:(UIApplication *)application {
    NSLog(@"应用从活跃状态到非活跃状态");
}
//应用进入后台时调用该方法并发出通知。这个阶段可以保存用户数据,释放一些资源。
- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"应用进入后台");
}
//应用进入前台,但是还没处于活跃状态时调用方法并发出通知。这个阶段可以恢复用户数据。
- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"应用进入前台,但是还没处于活跃状态");
}
//应用进入前台,处于活跃状态调用该方法并发出通知,这个状态可以保存UI状态。
- (void)applicationDidBecomeActive:(UIApplication *)application {
    NSLog(@"应用进入前台,处于活跃状态");
}
//应用终止时调用该方法。
- (void)applicationWillTerminate:(UIApplication *)application {
    NSLog(@"应用终止");
}

应用启动并进行初始化的时候会调用该方法,并发出通知。在这个阶段会初始化根视图控制器。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"应用启动并进行初始化");
    //初始化一个window对象
    self.window = [[UIWindow alloc] init];
    //创建一个screen并取其bounds属性再赋值给window的frame属性
    self.window.frame = [UIScreen mainScreen].bounds;
    //设置窗口背景颜色backgroundColor
    self.window.backgroundColor = [UIColor yellowColor];
    //使当前的窗口作为主窗口并显示在屏幕最前端
    [self.window makeKeyAndVisible];
    //把ViewController的对象作为window的根视图控制器(rootViewController),没有则会报错
    self.window.rootViewController = [[ViewController alloc] init];//不带xib的方法

//切换根视图控制器,让AViewControler作为window的根视图控制器(AViewControler是新创建的一个类,下面BViewController同理)
    self.window.rootViewController = [[AViewControlerViewController alloc] init];//没有设置颜色,默认为黑色

//带xib的方法,在创建时选中‘Also creat XIB file’
    BViewController *bVC = [[BViewController alloc] initWithNibName:@"BViewController" bundle:[NSBundle mainBundle]];
    self.window.rootViewController = bVC;

创建一个AppD类,替换NSStringFromClass([AppDelegate class])中的AppDelegate,让AppD作为UIAplication的委托对象

//需要遵循协议
@interface AppD : UIResponder<UIApplicationDelegate>
//创建window属性
@property (nonatomic,strong)UIWindow *window;

@end

//在AppD实现文件
//应用启动并进行初始化的时候会调用该方法,并发出通知。在这个阶段会初始化根视图控制器。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    //初始化window对象
    self.window = [[UIWindow alloc] init];
    //设置大小
    self.window.frame = [UIScreen mainScreen].bounds;
    //设置当前window为主窗口并显示在最前端
    [self.window makeKeyAndVisible];
   //创建ViewController对象,这是初始化一个什么控件都不带的对象
 ViewController *vc = [[ViewController alloc] init];
    //通过UIStoryboard创建一个storyboard对象
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
    //实例化一个ViewController对象,并带有一些需要的控件
    ViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"ViewController"];//(storyboard导航面板/Show the identity inspector/storyboard ID)
    //添加根视图控制器    
    self.window.rootViewController = vc;

    return  YES;
}

2013-03-26 07:19:40 hursing 阅读数 7249
  • 宏定义与预处理、函数函数库-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8171 人正在学习 去看看 朱有鹏

在Objective-C函数的入口处(第一行)加断点,可用esp指针来探查参数。

以esp为基址,往后的偏移分别是:

0:函数执行完毕后的返回地址(不是返回值的地址哦)

4:对象实例的指针,即self指针

8:selector,实际是一个char数组型的字符串,即char*

12:(如果有)第一个参数

…(前一个参数的基址+前一个参数所占的字节数):(如果有)第n个参数


由此,要调试这样一个函数

- (void)para1:(id)p1 para2:(CGRect)p2 para3:(CGPoint)p3 para4:(id)p4
{
    NSLog(@"para1:(id)p1 para2:(CGRect)p2 para3:(CGPoint)p3 para4:(id)p4");
}

- (void)viewDidLoad
{
    [self para1:[UIApplication sharedApplication] para2:CGRectMake(10, 20, 30, 40) para3:CGPointMake(50, 60) para4:self];

时,断点后可在gdb这样调试:

po *(id*)($esp+4)                  // 得到对象实例的描述。执行越过函数头部后,应为 po *(id*)($ebp+8),以下类同

p (char*)*(SEL*)($esp+8)     // 得到selector的名字

po *(id*)($esp+12)               // 得到p1的description

p *(CGRect*)($esp+16)       // 得到p2的各个成员值,输出结果为:“(CGRect) $1 = origin=(x=10, y=20) size=(width=30, height=40)”

p *(CGPoint*)($esp+32)   // 因为一个CGRect结构体占16字节(4个float),所以是“+32”,即“+16+16”, 得到p3的各个成员值,输出结果为:“(CGPoint) $4 = (x=50, y=60)”

po *(id*)($esp+40)       // 因为一个CGPoint结构体占8字节(2个float),所以是“+40”,即“+32+8”、得到p4的description

(gdb) po *(id*)($esp+4) 
<ViewController: 0x757f8c0>
(gdb) p (char*)*(SEL*)($esp+8) 
$1 = 0xf37b "para1:para2:para3:para4:"
(gdb) po *(id*)($esp+12) 
<UIApplication: 0x9250000>
(gdb) p *(CGRect*)($esp+16) 
$2 = {
  origin = {
    x = 10, 
    y = 20
  }, 
  size = {
    width = 30, 
    height = 40
  }
}
(gdb) p *(CGPoint*)($esp+32)
$3 = {
  x = 50, 
  y = 60
}
(gdb) po *(id*)($esp+40) 
<ViewController: 0x757f8c0>

注意:由于在第一行,push了ebp,会导致esp被修改,而第二行又立刻把esp的值赋给ebp,所以在执行经过函数的这些头部后,可以用ebp类似地访问,不过参数的偏移都需要+4。

下面是如何查看浮点型参数。

浮点型参数会通过SSE寄存器来传递,可以在gdb中这样查看:

p $xmm0

(lldb不能用上面的命令,暂没去研究用什么替代)

例如调试上例中的

CGRectMake(10, 20, 30, 40)

编译器会把参数反序送入xmm寄存器组,即40传入xmm0,30传入xmm1……

在CGRectMake加断点,执行到下图中的位置时输入命令


命令结果如下:
(gdb) p $xmm0
$1 = {
  v4_float = {0, 0, 0, 40}, 
  v2_double = {0, 5.4811317061554153e-315}, 
  v16_int8 = {0 <repeats 12 times>, 66, 32, 0, 0}, 
  v8_int16 = {0, 0, 0, 0, 0, 0, 16928, 0}, 
  v4_int32 = {0, 0, 0, 1109393408}, 
  v2_int64 = {0, 1109393408}, 
  uint128 = 35467839930368
}
因为SSE寄存器是128位的,gdb并不知道哪些bit是有意义的,所以列出了一些猜测的结果。

我们传入的是CGFloat,即float,故v4_float = {0, 0, 0, 40} 是有意义的。

当传入的是double型,则v2_double有意义。


转载请注明出处:http://blog.csdn.net/hursing

xcode反汇编调试iOS模拟器程序
(一)查看反汇编
(二)看懂反汇编
(三)查看Objective-C函数与参数
(四)自动断点应用之NSNotificationCenter
(五)调试objc_msgSend函数
(六)函数出入口处的处理与局部变量
(七)Debug与Release的区别

(八)反汇编自己的代码来掌握规则

2017-04-05 13:59:59 probuing 阅读数 305
  • 宏定义与预处理、函数函数库-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8171 人正在学习 去看看 朱有鹏

二维数组与函数

1.二维数组的元素作为函数参数

  • 二维数组的元素就相当于变量,作为函数参数与变量相同
~~ void test(char c);
~~ int main(int argc, const char * argv[]) {
~~     char cs[2][3] =
~~     {
~~         {'l', 'n', 'j'},
~~         {'l', 'm', 'j'}
~~     };
~~     printf("cs[0][0] = %c\n", cs[0][0]);
~~     test(cs[0][0]);
~~     printf("cs[0][0] = %c\n", cs[0][0]);
~~     return 0;
~~ }
~~ void test(char c)
~~ {
~~     c = 'w';
~~     printf("我被执行了\n");
~~ }
~~ 
~~ 输出结果:
~~ cs[0][0] = l
~~ 我被执行了
~~ cs[0][0] = l

2.二维数组中的一维数组作为函数

  • 二维数组的一维数组实际上就是一个一维数组,作为函数参数与一维数组相同
~~ void test(char c[]);
~~ int main(int argc, const char * argv[]) {
~~     char cs[2][3] =
~~     {
~~         {'l', 'n', 'j'},
~~         {'l', 'm', 'j'}
~~     };
~~     printf("cs[0][0] = %c\n", cs[0][0]);
~~     test(cs[0]);
~~     printf("cs[0][0] = %c\n", cs[0][0]);
~~     return 0;
~~ }
~~ void test(char c[])
~~ {
~~     c[0] = 'w';
~~     printf("我被执行了\n");
~~ }
~~ 输出结果:
~~ cs[0][0] = l
~~ 我被执行了
~~ cs[0][0] = w

3.二维数组作为函数参数

  • 二维数组作为函数参数是地址传递
  • 二维数组作为函数形参,参数中一维数组的元素个数不可以省略
~~ void test(char cs[2][]) // 错误写法
~~ {
~~     printf("我被执行了\n");
~~ }
~~ 
~~ void test(char cs[2][3]) // 正确写法
~~ {
~~     printf("我被执行了\n");
~~ }
~~ 
~~ void test(char cs[][3]) // 正确写法
~~ {
~~     printf("我被执行了\n");
~~ }
~~ 
  • 二维数组作为函数参数,在被调函数中不能获得其有多少行,需要通过参数传入。
~~ void test(char cs[2][3])
~~ {
~~     int row = sizeof(cs);
~~     printf("row = %zu\n", row);
~~ }
~~ 输出结果:
~~ row = 8
  • 二维数组作为函数参数,在被调函数中可以计算出二维数组有多少列
~~ void test(char cs[2][3])
~~ {
~~     size_t col = sizeof(cs[0]);
~~     printf("col = %zd\n", col);
~~ }
~~ 输出结果:
~~ col = 3
2019-04-10 23:07:46 sinat_33107803 阅读数 137
  • 宏定义与预处理、函数函数库-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8171 人正在学习 去看看 朱有鹏

Open函数——std::ofstream::open 

void open (const char* filename, ios_base::openmode mode = ios_base::out);

函数参数:输出就是文件的写入

  1. Filename    打开文件的路径和名称
  2. Ios::base    输入/输出模式
  3. ①   In (input)打开文件对文件进行读取(内部缓存区写入);

    ②   Out (output)打开文件对文件进行写入(内部缓存区的输出);

    ③   Ate (at end)从文件末尾开始输出;

    ④   Binary (binary)以二进制模式操作;

    ⑤   App (append)所有输出操作都发生在文件的末尾,附加到其现有内容;

    ⑥   Trunc (truncate)文件打开之前存在的任何内容都将被丢弃。 

Write函数——std::ostream::write

ostream& write (const char* s, streamsize n);

函数描述:写入数据块,将由s指向的数组的前n个字符插入到流中。复制的过程

参数描述:

  • S:指向至少n个字符的数组的指针;
  • N要插入的字符数
  • 返回值:ostream对象(*this)

Read函数——std::istream::read

istream& read (char* s, streamsize n);

函数描述:读取数据块,从流中提取n个字符,并将它们存储在s指向的数组中。只是复制

参数描述:

  • S:指向存储提取字符的数组的指针
  • N:要提取的字数。
  • 返回值:istream对象(*this)

Seekg函数——std::istream::seekg

istream& seekg (streampos pos);
istream& seekg (streamoff off, ios_base::seekdir way);

函数描述:在输入序列中设置位置,设置要从输入流中提取的下一个字符的位置定位作用

参数描述:

  • Off偏移量,相对于方法参数。(带符号的整型)
  • Way:相对位置:begcurend
  • 返回值:istream对象(*this)

Tellg函数——std::istream::tellg

streampos tellg();

函数描述:获取输入序列中的位置,返回当前字符在输入流中的位置。

2013-01-14 20:42:58 fantoms 阅读数 12
  • 宏定义与预处理、函数函数库-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8171 人正在学习 去看看 朱有鹏
Xcode4.2前的main:


int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}



Xcode4.5的main
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, nil]));
}
}


UIApplication是初始化程序的核心,它接受4个参数。
其中argc和argv两个参数来自于main()接受的两个参数;另外两个String型参数分别表示程序的主要类(principal class)和代理类(delegate class)。
如果主要类(principal class)为nil,则默认为UIApplication;如果代理类(delegate class)为nil,则程序假设程序的代理来自Main nib文件。如果这两个参数任意一个不为nil,则UIApplicationMain()函数则会根据参数创建相应的功能类。
因此,如果程序中使用自定义的UIApplication类的子类(不建议继承UIApplication类建立自定义的子类),你需要将你的自定义类名作为第3个参数传进来。

IOS 声明周期:

[img]http://dl.iteye.com/upload/attachment/0079/2622/e63fa531-589e-3dab-9935-243393701d53.png[/img]

iOS App生命周期

阅读数 170

没有更多推荐了,返回首页