您的位置:时时app平台注册网站 > 编程知识 > 做题种类之4---后天不做题

做题种类之4---后天不做题

2019-09-15 01:00

在objc-runtime-new.mm中有_read_images这个方法,我们来看一下

图片 1

开始

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],为2;&a 1不是首地址 1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)   int *ptr=(int *)(&a 1);   则ptr实际是&(a[5]),也就是a 5

2

char *c[] = { "ENTER", "NEW", "POINT", "FIRST" };
char **cp[] = { c 3, c 2, c 1, c };
char ***cpp = cp;
int main(void)
{
printf("%s", ** cpp);
printf("%s", *--* cpp 3);
printf("%s", *cpp[-2] 3);
printf("%sn", cpp[-1][-1] 1);
return 0;
}

感觉这题能分析清楚,这类型的基本没问题了。
分析:
· 这题跟上题刚好有个对比上题为什么是数组大小的偏移呢?因为上踢是一个数组指针,而第二题是一个指向数组的指针而已;

char (*p)[3] ; char *p[3]
这两者的区别要记住

· ** 然后就是对表达式优先级还有结合性,所以在*--* cpp 3这个里面,是 3操作是最后进行的,然后最开始就是 cpp.........*

· ** 还有一点就是int *a[3]; a 3 = a[3];类比这里c[0] 3,有点像二维数组,但c[0]里面的还是一个字符串数组,char *a= "ENTER" **;

· ** 还有一个就是p为指针 * p这个会对p进行地址指向 1操作,但是 p[0 1]只是单单获取而已!**

(1) c是指向一个有4个char类型数据的数组的char类型指针,然后cp也只是指向char类型的指针,cpp同样。 先对cpp所指向的地址做 1操作,然后做两次取址操作,先从cp[0 1]拿出c 2,然后再拿出“POINT”打印
(2)注意经过第一次打印这时候的cpp已经是指向了cp第二个数据。这时又在指向第三个就是c 1,这时候是再执行“--”操作,对指向“NEW”的指针进行-1操作,这是指针指向“ENTER”,再进行c[0] 3的操作;
(3)首先对cpp指向的地址-2操作,现在指向重新变成c 3,最后就是c[3] 3
(4) 从第二个输出开始cpp指向的是c 1,这时候先-1地址获取到的是c 2,然后再指向c 2的指针再进行-1操作,再进行c[2] 1;

4 下面输出的值是多少

#include <stdio.h>
void func(int* ptr, int &value)
{
ptr = &value;
}
int main()
{
int i = 10, j = 5;
int *ptr = &i;
func( ptr, j);
printf("%d", *ptr);
return 0;
}

这里的point应该是在函数参数上。

5
用变量a给出下面的定义
a) 一个整型数
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 that 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]; // 一个有10个整型数的数组 An array of 10 integers
e) int *a[10]; // 一个有10个指针的数组 An array of 10 pointers to integers
f) int (*a)[10]; // 一个指向有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); // 一个有10个指针的数组,指向一个整形函数并有一个整形参数 An array of 10 pointers to functions that take an integer argument and return an integer

参看网页

接下来的是真正关于iOS的问题

  1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?

Object-c的类不可以多重继承;可以实现多个接口,通过实现多个接口可以完成C 的多重继承;Category是类别,一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系。
类别主要有3个作用:
(1)将类的实现分散到多个不同文件或多个不同框架中。
(2)创建对私有方法的前向引用。
(3)向对象添加非正式协议。
继承可以增加,修改或者删除方法,并且可以增加属性。

2.#import 跟#include 又什么区别,@class呢, #import<> 跟 #import”"又什么区别?

#import是Objective-C导入头文件的关键字,#include是C/C 导入头文件的关键字,使用#import头文件会自动只导入一次,不会重复导入,相当于#include和#pragma once;@class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包#import<>用来包含系统的头文件,#import””用来包含用户头文件。

3.属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?

readwrite 是可读可写特性;需要生成getter方法和setter方法时

readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变

assign 是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;

retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会 1;

copy 表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时。

nonatomic 非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic

5.对于语句NSString *obj = [[NSData alloc] init]; obj在编译时和运行时分别时什么类型的对象?

编译时是NSString的类型;运行时是NSData类型的对象
**解释: **
首先,声明 NSString *testObject是告诉编译器,obj是一个指向某个Objective-C对象的指针。因为不管指向的是什么类型的对象,一个指针所占的内存空间都是固定的,所以这里声明成任何类型的对象,最终生成的可执行代码都是没有区别的。这里限定了NSString只不过是告诉编译器,请把obj当做一个NSString来检查,如果后面调用了非NSString的方法,会产生警告。接着,你创建了一个NSData对象,然后把这个对象所在的内存地址保存在obj里。那么运行时,obj指向的内存空间就是一个NSData对象。你可以把obj当做一个NSData对象来用。

6.常见的object-c的数据类型有那些, 和C的基本数据类型有什么区别?如:NSInteger和int

object-c的数据类型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,这些都是class,创建后便是对象,而C语言的基本数据类型int,只是一定字节的内存空间,用于存放数值;而object-c的NSNumber包含有父类NSObject的方法和NSNumber自己的方法,可以完成复杂的操作。

类对象都继承于NSOject,都能使用NSObject的方法,并且拥有类的特性,可使用Category进行扩展。

7 instancetypeid区别?

8 内存管理。

9浅复制和深复制的区别?

浅复制:A,B同样拥有同一个对象的地址。这样的就称为浅复制。
深复制:A,B拥有相同内容,但是内容的地址不一样。其实在传递NSArray的时候,使用[NSArray mutablecopy],原理就是开辟一个新的内存空间存储要复制的内容,这个内容一样地址不一样的就是深复制。

后续学会怎么将一个自定义类实现nscopy,nsmutablecopy协议。

10
类别(category)和类扩展(extension)的区别。
答案:category和extensions的不同在于 后者可以添加属性。另外后者添加的方法是必须要实现的。
extensions可以认为是一个私有的Category

11 解释一下KVO 和 KVC?

kvo:key-value-Observing。顾名思义就是一种observer 模式用于监听property的变化,KVO跟NSNotification有很多相似的地方,用addObserver:forKeyPath:options:context:去start observer, 用removeObserver:forKeyPath:context去stop observer, 回调就是observeValueForKeyPath:ofObject:change:context:KVO给我们提供了更少的代码,和比NSNotification好处,不需要修改被观察的class, 永远都是观察你的人做事情。

- (void)removeObservation {
[self.object removeObserver:self
forKeyPath:self.property];
}

  • (void)addObservation {
    [self.object addObserver:self forKeyPath:self.property
    options:0
    context:(__bridge void*)self];
    }
  • (void)observeValueForKeyPath:(NSString *)keyPath
    ofObject:(id)object
    change:(NSDictionary *)change
    context:(void *)context {
    if ((__bridge id)context == self) {
    // 只处理跟我们当前class的property更新
    }
    else {
    [super observeValueForKeyPath:keyPath ofObject:object
    change:change context:context];
    }
    }

kvc:key-value-coding它能让我们可以通过name(key)的方式访问property, 不必调用明确的property accssor, 如我们有个property叫做foo, 我们可以foo直接访问它,同样我们也可以用KVC来完成[Object valueForKey:@“foo”]

KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,常用的KVC操作方法如下:
动态设置: setValue:属性值 forKey:属性名
(用于简单路径)
、**setValue:属性值 forKeyPath:属性路径
**(用于复合路径,例如Person有一个Account类型的属性,那么person.account就是一个复合属性)
动态读取: **valueForKey:属性名
valueForKeyPath:属性名
**(用于复合路径)

放两个不错的blog:
A...
B...

12 代理的作用?
代理的作用是改变或者传递控制链。
1、监听事件:A是监听B的一些行为,则A成为B的代理
2、消息传递:A想告诉B一些事情,则B成为A的代理

13
我们说的obc是动态运行时语言是什么意思?
答案:多态。 主要是将数据类型的确定由编译时,推迟到了运行时。
这个问题其实浅涉及到两个概念,运行时和多态。
简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
多态:不同对象以自己的方式响应相同的消息的能力叫做多态。

哎,看着看着就不想这么应试的准备,很多知识点虽然我用过,但是自己是总结不出来这么细,但是有些新的知识单单仅仅这么去看,完全又是应试的看,根本脱离了我学习iOS的乐趣。end..

二、 怎么证明meta class中保存的是类方法?

更不是(int *a)[4]

面对自己实力不足,而又急切需要一份不错的工作,感觉自己都没有信心在那么多校招企业里面拿到自己需要的,所以只能尽可能的做一些事情把,也不能坐以待毙,操作系统,数据结构,计算机网络,只能有机会一点点来了。

  • int* a[4] 指针数组 数组a中的元素都为int型指针
  • int [4] 数组指针 指向数组a的指针

而是int [3][3]

一、 什么是指针数组、什么是数组指针、什么二级指针?

指针数组与数组指针

指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针

数组指针:a pointer to an array,即指向数组的指针

还要注意的是他们用法的区别,下面举例说明。

int* a[4]     指针数组     

                 表示:数组a中的元素都为int型指针    

                 元素表示:*a[i]   *(a[i])是一样的,因为[]优先级高于*

int (*a)[4]   数组指针     

                 表示:指向数组a的指针

                 元素表示:(*a)[i]  

#include <iostream>

using namespace std;

 

int main()

{

int c[4]={1,2,3,4};

int *a[4]; //指针数组

int (*b)[4]; //数组指针

b=&c;

//将数组c中元素赋给数组a

for(int i=0;i<4;i )

{

a[i]=&c[i];

}

//输出看下结果

cout<<*a[1]<<endl; //输出2就对

cout<<(*b)[2]<<endl; //输出3就对

return 0;

}

今天的主题是:

array的类型既不是int **

  • 指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针
  • 数组指针:a pointer to an array,即指向数组的指针

 

char *argv[3]={{"abcdefg"},{"1234567"},{"q1w2e3r"}}; char **p = argv; //二级指针printf("*p=%s/n",*p); //*p=abcdefgprintf=%s/n",*; //*=1234567printf=%s/n",*; //*=q1w2e3r

传递二维数组参数

int func(int **array, int m, int n) {

...

printf("t%d", *(*array i*n j));

...

}

 

int main() {

  int array[3][3] = {

{1,2,3},

{4,5,6},

{7,8,9}

};

...

func(array,3,3);

 ...

}

这样传递二维数组是错的,因为类型不匹配,是因为数组实际类型是int [3][3],在作为右值时可以被转化为int (*)[3],它们都和int **不同,自然不可用。

 

法一 直接使用数组类型:因为数组实际类型是int [3][3]

可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以指定所有维数的大小,也可以省略第一维的大小说明,如:

 

void Func(int array[3][10]);

 

void Func(int array[][10]);

 

二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是不合法的:

 

void Func(int array[][]);

 

因为从实参传递来的是数组的起始地址,在内存中按数组排列规则存放(按行存放),而并不区分行和列,如果在形参中不说明列数,则系统无法决定应为多少行多 少列,不能只指定一维而不指定第二维

 

法二.一维数组指针作为形参

void func2(int (*pArray)[10])

{

 

}

 

void func2_1(int (*pArray)[]) //编译通过,无法调用

{

 

}

 

int main()

{

int array[10][10];

func2(array);

}

把array[0] 数组的指针传给了func2 因为array是指向10个元素的数组的指针,(*array)就是array[0],(*array)[0] 就是array[0][0]

 

法三.二维数组引用作为形参

void func3(int (&pArray)[10][10])

{

 

}

 

int main()

{

int array[10][10];

func3(array);

}

以下是一维数组引用的例子

 

#include <iostream>

using namespace std;

void output(int (&a)[5])

{

for(int i = 0; i < 5; i )

cout<<a[i]<<endl;

}

int main()

{

int a[5]={0};

output(a);

getchar();

return 0;

}

 

法四。二维数组指针作为形参

void func4(int (*pArray)[10][10])

{

 

}

 

int main()

{

int array[10][10];

func4(&array);

 

}

那二级指针是什么捏。如下:

 

  • C语言指针的小知识点
  • 怎么证明meta class中保存的是类方法

int (*a)[4] a是指向一个有4个元素的数组的指针,事实上这个a此时指向a[0],指向数组,就是说a里保存着数组的地址,就是1000

for (EACH_HEADER) { category_t **catlist = _getObjc2CategoryList(hi, &count); for (i = 0; i < count; i  ) { category_t *cat = catlist[i]; Class cls = remapClass(cat->cls); bool classExists = NO; if (cat->instanceMethods || cat->protocols || cat->instanceProperties) { addUnattachedCategoryForClass(cat, cls, hi); if (cls->isRealized { remethodizeClass; classExists = YES; } } if (cat->classMethods || cat->protocols) { addUnattachedCategoryForClass(cat, cls->ISA; if (cls->ISA()->isRealized { remethodizeClass(cls->ISA; } } } }

int array[3][3];

这是加载category的代码,我们看到他区分了instanceMethods和classMethods。并且将classMethods加入了cls->ISA(),也就是meta class。

只是作为右值时才转换成

举个具体栗子:

更多的见:

由上可见,可以简单的把二级指针理解为指针数组。

前面介绍过,C语言允许把一个二维数组分解为多个一维数组来处理。因此数组a可分解为三个一维数组,即a[0]、a[1]、a[2]。每一个一维数组又含有四个元素。
图片 2图片 3
图片 4

数组及数组元素的地址表示如下:从二维数组的角度来看,a是二维数组名,a代表整个二维数组的首地址,也是二维数组0行的首地址,等于1000。a 1代表第一行的首地址,等于1008。如图:
图片 5

(int *array)[N] 和int **的区别

图片 6

Int ** p,就是一个指针,这个指针指向了int* 也就是一个整型数组,p是指向了整数数组的指针,p中是整数数组的地址,(int *array)[N] 和int **的区别就在于每行的元素个数固不固定

例如a[0]数组,含有a[0][0],a[0][1],a[0][2],a[0][3]四个元素。

设有整型二维数组a[3][4]如下:
0   1   2   3
4   5   6   7
8   9  10  11 
它的定义为:
    int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}
设数组a的首地址为1000,各下标变量的首地址及其值如图所示。
图片 7

本文由时时app平台注册网站发布于编程知识,转载请注明出处:做题种类之4---后天不做题

关键词:

  • 上一篇:没有了
  • 下一篇:没有了