热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

J_Knight_iOS高级面试题基础题解答

最近从公司离职了,准备了一下接下来的面试,翻出了J_Knight的高级面试题复习了一下面试iOS基础题分类和扩展有什么区别?可以分别用来做

最近从公司离职了,准备了一下接下来的面试,翻出了J_Knight的高级面试题复习了一下面试

iOS 基础题

分类和扩展有什么区别?可以分别用来做什么?分类有哪些局限性?分类的结构体里面有哪些成员?

区别: extension在编译期决议 它伴随类的产生而产生,亦随之一起消亡 category则完全不一样,它是在运行期决议的 extension可以添加实例变量,而category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。

分类应用 可以把类的实现分开在几个不同的文件里面。这样做有几个显而易见的好处, 1:可以减少单个文件的体积 2:可以把不同的功能组织到不同的category里 3:可以由多个开发者共同完成一个类 4:可以按需加载想要的category 等等。 5:声明私有方法

扩展应用 extension一般用来隐藏类的私有信息

struct category_t { constchar*name;//类的名字(name) classref_t cls;//类(cls) struct method_list_t *instanceMethods; //category中所有给类添加的实例方法的列表(instanceMethods) structmethod_list_t *classMethods;//category中所有添加的类方法的列表(classMethods) structprotocol_list_t *protocols; //category实现的所有协议的列表(protocols) structproperty_list_t *instanceProperties;//category中添加的所有属性(instanceProperties) };

讲一下atomic的实现机制;为什么不能保证绝对的线程安全(最好可以结合场景来说)?

atomic只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的,因此在多线程编程时,线程安全还需要开发者自己来处理.关 于选择:atomic系统生成的getter、setter会保证get、set操作的安全性,但相对nonatomic来说,atomic要更耗费资源,且速度要慢,故在iPhone等小型设备上,如果没有多线程之间的通讯,使用nonatomic是更好的选 atomic系统自动生成的getter/setter方法会进行加锁操作 nonatomic系统自动生成的getter/setter方法不会进行加锁操作

例如:线程1调用了某一属性的setter方法并进行到了一半,线程2调用其getter方法,那么会执行完setter操作后,在执行getter操作,线程2会获取到线程1 setter后的完整的值. 当几个线程同时调用同一属性的setter、getter方法时,会get到一个完整的值,但get到的值不可控.例如:线程1 调用getter线程2 调用setter线程3 调用setter这3个线程并行同时开始,线程1会get到一个值,但是这个值不可控,可能是线程2,线程3 set之前的原始值,可能是线程2set的值,也可能是线程3 set的值

被weak修饰的对象在被释放的时候会发生什么?是如何实现的?知道sideTable么?里面的结构可以画出来么?

https://blog.csdn.net/future_one/article/details/81606895 。 浅谈iOS之weak底层实现原理
https://www.jianshu.com/p/f331bd5ce8f8 浅谈iOS之weak底层实现原理

关联对象有什么应用,系统如何管理关联对象?其被释放的时候需要手动将所有的关联对象的指针置空么?

1.2 如何关联对象
runtime提供了給我们3个API以管理关联对象(存储、获取、移除):
123456 //关联对象void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)//获取关联的对象id objc_getAssociatedObject(id object, const void *key)//移除关联的对象void objc_removeAssociatedObjects(id object)
其中的参数
id object:被关联的对象
const void *key:关联的key,要求唯一id value:关联的对象
objc_AssociationPolicy policy:内存管理的策略void objc_removeAssociatedObjects(id object);,会移除所有的关联,包括其他模块添加的,因此应该用 objc_setAssociatedObject(..,nil,..) 的方式去卸载。
苹果官方文档说 OBJC_ASSOCIATION_ASSIGN 相当于一个 weak reference,但其实等于 assign/unsafe_unretained。
对于与weak的区别不在本文讨论范围内,浅显的区别在于变量释放后,weak 会把引用置空,unsafe_unretained会保留内存地址,一旦获取可能会野指针闪退。详情:https://www.jianshu.com/p/1feae48a5dda AssociatedObject关联对象原理实现

KVO的底层实现?如何取消系统默认的KVO并手动触发(给KVO的触发设定条件:改变的值符合某个条件时再触发KVO)?

KVO是通过isa-swizzling技术实现的(这句话是整个KVO实现的重点)。
在运行时根据原类创建一个中间类,这个中间类是原类的子类,
并动态修改当前对象的isa指向中间类。并且将class方法重写,返回原类的
Class。1.在运行的时候创建被监类的子类2.在子类中重写父类属性的set方法(故kvo之监听属性)3注册这个子类4.修改当前被监听的isa指针指向子类5.实现set函数在分析KVO的内部实现之前,先来分析一下KVO的存储结构,主要用到了以下几个类:
GSKVOInfo
GSKVOPathInfo
GSKVOObservation
@interface GSKVOInfo : NSObject
{NSObject *instance; // Not retained. observer保存观察者 注意这里也是 Not retained 释放之后,在调用会崩溃,需要在对象销毁前,移除所有观察者GSLazyRecursiveLock *iLock;NSMapTable *paths; paths 用于保存keyPath 到 GSKVOPathInfo 的映射:
}
@interface GSKVOPathInfo : NSObject
{
@publicunsigned recursion;unsigned allOptions; 保存了观察者的options集合NSMutableArray *observations; 保存了所有的观察者(GSKVOObservation 类型)NSMutableDictionary *change; 保存了KVO触发要传递的内容
}@interface GSKVOObservation : NSObject
{
@publicNSObject *observer; // Not retained (zeroing weak pointer)void *context; 都是添加观察者时传入的参数int options; 都是添加观察者时传入的参数
}
@endKVO内部多次用到了KVC
1️⃣ 重写 setValue:forKey
2️⃣ 使用valueForKey --- valueForKeyPath获取属性的值,尤其是在使用点语法的时候,只有valueForKeyPath可以获得深层次的属性值。
所以KVO是基于KVC而实现的。详细链接:https://www.jianshu.com/p/d6e4ba25acd2

Autoreleasepool所使用的数据结构是什么?AutoreleasePoolPage结构体了解么?

Autorelease pool的实现原理Autorelease pool是有objc_autoreleasePoolpush和objc_autoreleasePoolpop实现objc_autoreleasePoolpush和objc_autoreleasePoolpop是由AutoreleasePoolPage 实现的class AutoreleasePoolPage { //大小4096 字节字节 双向列列表实现的
magic_t const magic; 用于对当前 AutoreleasePoolPage 完整性的校验
id *next; 指向了下一个为空的内存地址
pthread_t const thread; /当前所在的线程
AutoreleasePoolPage * const parent; 头节点AutoreleasePoolPage *child; 尾节点 。
uint32_t const depth; 深度
uint32_t hiwat;
POOL_SENTINEL(哨兵对象)
id next next 指向了下一个为空的内存地址,如果 next 指向的地址加入一个 object
};在每个自动释放池初始化调用 objc_autoreleasePoolPush 的时候,都会把一个 POOL_SENTINEL push 到自动释放池的栈顶,并且返回这个 POOL_SENTINEL 哨兵对象。
而当方法 objc_autoreleasePoolPop 调用时,就会向自动释放池中的对象发送 release 消息,直到第一个 POOL_SENTINEL:注意:在这里会进入一个比较关键的方法 autoreleaseFast,并传入哨兵对象 POOL_SENTINEL:
void *objc_autoreleasePoolPush(void) {return AutoreleasePoolPage::push();
}
static inline void *push() {return autoreleaseFast(POOL_SENTINEL);
}
static inline id *autoreleaseFast(id obj) {
AutoreleasePoolPage *page = hotPage(); hotPage 可以理解为当前正在使用的 AutoreleasePoolPage。
if (page && !page->full()) { return page->add(obj); } 有 hotPage 并且当前 page 不满,有 hotPage 并且当前 page 不满 调用 page->add(obj) 方法将对象添加至 AutoreleasePoolPage 的栈中
else if (page) {
return autoreleaseFullPage(obj, page); 有 hotPage 并且当前 page 已满,调用 autoreleaseFullPage 初始化一个新的页,调用 page->add(obj) 方法将对象添加至 AutoreleasePoolPage 的栈中
} else {
return autoreleaseNoPage(obj); } 无 hotPage 调用 autoreleaseNoPage 创建一个 hotPage}
id *add(id obj) {id *ret = next;*next = obj;next++;return ret;
}
这个方法其实就是一个压栈的操作,将对象加入 AutoreleasePoolPage 然后移动栈顶的指针
它会从传入的 page 开始遍历整个双向链表,直到:
查找到一个未满的 AutoreleasePoolPage
使用构造器传入 parent 创建一个新的 AutoreleasePoolPage
在查找到一个可以使用的 AutoreleasePoolPage 之后,会将该页面标记成 hotPage,然后调动上面分析过的 page->add 方法添加对象。既然当前内存中不存在 AutoreleasePoolPage,就要从头开始构建这个自动释放池的双向链表,也就是说,新的 AutoreleasePoolPage 是没有 parent 指针的。
初始化之后,将当前页标记为 hotPage,然后会先向这个 page 中添加一个 POOL_SENTINEL 对象,来确保在 pop 调用的时候,不会出现异常。
最后,将 obj 添加到自动释放池中。4.3 objc_autoreleasePoolPop 方法
static inline void pop(void *token) {
AutoreleasePoolPage *page = pageForPointer(token); //使用 pageForPointer 获取当前 token 所在的 AutoreleasePoolPagestatic AutoreleasePoolPage *pageForPointer(const void *p) {
return pageForPointer((uintptr_t)p);}
static AutoreleasePoolPage *pageForPointer(uintptr_t p) {AutoreleasePoolPage *result;
uintptr_t offset = p % SIZE;
assert(offset >= sizeof(AutoreleasePoolPage));
result = (AutoreleasePoolPage *)(p - offset); result->fastcheck();
return result;}
pageForPointer 方法主要是通过内存地址的操作,获取当前指针所在页的首地址 将指针与页面的大小,也就是 4096 取模,得到当前指针的偏移量,因为所有的 AutoreleasePoolPage 在内存中都是对齐的 而最后调用的方法 fastCheck() 用来检查当前的 result 是不是一个 AutoreleasePoolPage。
id *stop = (id *)token;
page->releaseUntil(stop); // 调用 releaseUntil 方法释放栈中的对象,直到 stop //它的实现还是很容易的,用一个 while 循环持续释放 AutoreleasePoolPage 中的内容,直到 next 指向了 stop。
if (page->child) {
if (page->lessThanHalfFull()) { page->child->kill(); //调用 child 的 kill 方法
} else if (page->child->child){ page->child->child->kill();
} } }整个自动释放池 autoreleasepool 的实现以及 autorelease 方法都已经分析完了,我们再来回顾一下文章中的一些内容:
自动释放池是由 AutoreleasePoolPage 以双向链表的方式实现的。
当对象调用 autorelease 方法时,会将对象加入 AutoreleasePoolPage 的栈中。
调用 AutoreleasePoolPage::pop 方法会向栈中的对象发送 release 消息。作者:卡布达巨人
链接:https://juejin.im/post/5a66e28c6fb9a01cbf387da1
来源:掘金

讲一下对象,类对象,元类,跟元类结构体的组成以及他们是如何相关联的?为什么对象方法没有保存的对象结构体里,而是保存在类对象的结构体里?

www.cnblogs.com/wsnb/p/6163…

class_ro_t 和 class_rw_t 的区别?

class_rw_t 和 class_ro_t
ObjC 类中的属性、方法还有遵循的协议等信息都保存在 class_rw_t 中:
struct class_rw_t {uint32_t flags;uint32_t version;const class_ro_t *ro;method_array_t methods;property_array_t properties;protocol_array_t protocols;Class firstSubclass;Class nextSiblingClass;
};
其中还有一个指向常量的指针 class_ro_t,其中存储了当前类在编译期就已经确定的属性、方法以及遵循的协议。
struct class_ro_t {uint32_t flags;uint32_t instanceStart;uint32_t instanceSize;uint32_t reserved;const uint8_t * ivarLayout;const char * name;method_list_t * baseMethodList;protocol_list_t * baseProtocols;const ivar_list_t * ivars;const uint8_t * weakIvarLayout;property_list_t *baseProperties;
};
在编译期间类的结构中的 class_data_bits_t *data 指向的是一个 class_ro_t * 指针:isa 是指向元类的指针,不了解元类的可以看:Classes and Metaclasses
super_class 指向当前类的父类
cache 用于缓存指针和 vtable,加速方法的调用
bits 就是存储类的方法、属性、遵循的协议等信息的地方然后在加载 ObjC 运行时的过程中在 realizeClass 方法中:
从 class_data_bits_t 调用 data 方法,将结果从 class_rw_t 强制转换为 class_ro_t 指针
初始化一个 class_rw_t 结构体
设置结构体 ro 的值以及 flag
最后设置正确的 data。但是,在这段代码运行之后 class_rw_t 中的方法,属性以及协议列表均为空。这时需要 realizeClass 调用 methodizeClass 方法来将类自己实现的方法(包括分类)、属性和遵循的协议加载到 methods、 properties 和 protocols 列表中。详情:https://blog.csdn.net/fishmai/article/details/71157861

iOS 中内省的几个方法?class方法和objc_getClass方法有什么区别?

Class objc_getClass(const chat *aClassName)
1:Class objc_getClass(const chat *aClassName)
1> 传入字符串类名
2> 返回对应的类对象Class object_getClass(id obj)
2. Class object_getClass(id obj)
1> 传入的obj可能是instance对象,class对象、meta-class对象
2> 返回值
a:如果是instance对象,返回class对象
b:如果是class对象,返回meta-class对象
c:如果是meta-class对象,返回NSObject(基类)的meta-class对象- (class)class、+(class)class
3:- (class)class、+(class)class
1>返回的就是类对象结论:当obj为实例变量时,object_getClass(obj)与[obj class]输出结果一直,均获得isa指针,即指向类对象的指针。
总结:经上面初步的探索得知,object_getClass(obj)返回的是obj中的isa指针;而[obj class]则分两种情况:一是当obj为实例对象时,[obj class]中class是实例方法:- (Class)class,返回的obj对象中的isa指针;二是当obj为类对象(包括元类和根类以及根元类)时,调用的是类方法:+ (Class)class,返回的结果为其本身。作者:洲洲哥
链接:https://www.jianshu.com/p/5cfd52d222f0
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

在运行时创建类的方法objc_allocateClassPair的方法名尾部为什么是pair(成对的意思)

动态创建类
动态创建类涉及到以下几个函数:
12345678 // 创建一个新类和元类Class objc_allocateClassPair ( Class superclass, const char *name, size_t extraBytes );// 销毁一个类及其相关联的类void objc_disposeClassPair ( Class cls );// 在应用中注册由objc_allocateClassPair创建的类void objc_registerClassPair ( Class cls );
objc_allocateClassPair函数:如果我们要创建一个根类,则superclass指定为Nil。extraBytes通常指定为0,该参数是分配给类和元类对象尾部的索引ivars的字节数。
为了创建一个新类,我们需要调用objc_allocateClassPair。然后使用诸如class_addMethod,class_addIvar等函数来为新创建的类添加方法、实例变量和属性等。完成这些后,我们需要调用objc_registerClassPair函数来注册类,之后这个新类就可以在程序中使用了。
实例方法和实例变量应该添加到类自身上,而类方法应该添加到类的元类上。
objc_disposeClassPair函数用于销毁一个类,不过需要注意的是,如果程序运行中还存在类或其子类的实例,则不能调用针对类调用该方法。http://www.cocoachina.com/ios/20141031/10105.html
https://blog.csdn.net/hypercode/article/details/53931517

一个int变量被__block修饰与否的区别?

Block的本质<一>http://www.cocoachina.com/ios/20180910/24846.html理清 Block 底层结构及其捕获行为 https://juejin.im/post/5bb09160f265da0adb30e30diOS底层原理总结 - 探寻block的本质&#xff08;一&#xff09; http://www.cocoachina.com/ios/20180628/23965.htmliOS底层原理总结 - 探寻block的本质&#xff08;二&#xff09; http://www.cocoachina.com/ios/20180628/23968.htmliOS 看懂此文&#xff0c;你的block再也不需要WeakSelf弱引用了! http://www.cocoachina.com/ios/20180110/21817.htmliOS中Block的用法&#xff0c;举例&#xff0c;解析与底层原理&#xff08;这可能是最详细的Block解析 . http://www.cocoachina.com/ios/20180424/23147.html

为什么在block外部使用__weak修饰的同时需要在内部使用__strong修饰&#xff1f;

关于使用__weak和__strong大家都看到别人在block里面使用self或者self的属性的时候要使用__weak修饰self&#xff0c;然后才能block里面使用&#xff0c;在block里面使用的时候又将weakSelf使用__strong修饰进行使用,比如&#xff1a;
__weak __typeof(self) weakSelf &#61; self;
self.block &#61; ^{__strong __typeof(self) strongSelf &#61; weakSelf; [strongSelf doSomeThing];[strongSelf doOtherThing];
};
为什么使用weakSelf通过 clang -rewrite-objc 源代码文件名 将代码转为c&#43;&#43;代码(实质是c代码)&#xff0c;可以看到block是一个结构体&#xff0c;它会将全局变量保存为一个属性&#xff08;是__strong的&#xff09;&#xff0c;而self强引用了block这会造成循环 引用。所以需要使用__weak修饰的weakSelf。
为什么在block里面需要使用strongSelf是为了保证block执行完毕之前self不会被释放&#xff0c;执行完毕的时候再释放。这时候会发现为什么在block外边使用了__weak修饰self&#xff0c;里面使用__strong修饰weakSelf的时候不会发生循环引用&#xff1f;&#xff01;PS&#xff1a;strongSelf只是为了保证在block内部执行的时候不会释放&#xff0c;但存在执行前self就已经被释放的情况&#xff0c;导致strongSelf&#61;nil。注意判空处理。
不会引起循环引用的原因因为block截获self之后self属于block结构体中的一个由__strong修饰的属性会强引用self&#xff0c; 所以需要使用__weak修饰的weakSelf防止循环引用。block使用的__strong修饰的weakSelf是为了在block&#xff08;可以理解为函数&#xff09;生命周期中self不会提前释放。strongSelf实质是一个局部变量&#xff08;在block这个“函数”里面的局部变量&#xff09;&#xff0c;当block执行完毕就会释放自动变量strongSelf&#xff0c;不会对self进行一直进行强引用。
总结外部使用了weakSelf&#xff0c;里面使用strongSelf却不会造成循环&#xff0c;究其原因就是因为weakSelf是block截获的属性&#xff0c;而strongSelf是一个局部变量会在“函数”执行完释放。

RunLoop的作用是什么&#xff1f;它的内部工作机制了解么&#xff1f;&#xff08;最好结合线程和内存管理来说&#xff09;

https://juejin.im/post/5af590c5f265da0b7964f1c2 iOS底层原理探究-Runloop
https://juejin.im/post/5afcf305f265da0b8e7f9b74 RunLoop终极解析:输入源&#xff0c;定时源&#xff0c;观察者&#xff0c;线程间通信&#xff0c;端口通信&#xff0c;NSPort&#xff0c;NSMessagePort&#xff0c;NSMachPort&#xff0c;NSPortMessage https://juejin.im/post/5add46606fb9a07abf721d1d iOS底层原理总结 - RunLoop
https://juejin.im/post/58fc3ec8a0bb9f0065bd2889 iOS RunLoop 探究 http://www.cocoachina.com/ios/20180814/24550.html 老司机出品——源码解析之RunLoop详解
https://juejin.im/post/5aca2b0a6fb9a028d700e1f8 iOS RunLoop详解
http://www.cocoachina.com/ios/20180522/23447.html iOS开发·RunLoop源码与用法完全解析http://www.cocoachina.com/ios/20180626/23932.html 深入理解RunLoop

哪些场景可以触发离屏渲染&#xff1f;&#xff08;知道多少说多少&#xff09;

  • shouldRasterize&#xff08;光栅化&#xff09;
  • masks&#xff08;遮罩&#xff09;
  • shadows&#xff08;阴影&#xff09;
  • edge antialiasing&#xff08;抗锯齿&#xff09;
  • group opacity&#xff08;不透明&#xff09;
  • 复杂形状设置圆角等
  • 渐变

作者&#xff1a;J_Knight_ 链接&#xff1a;juejin.im/post/5b5615… 来源&#xff1a;掘金 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。

转:https://juejin.im/post/5cf37da8f265da1bc94ed6b5



推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
author-avatar
450651324_43c723
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有